/[cvs]/eggdrop1.9/modules/botnet/botnet.c
ViewVC logotype

Contents of /eggdrop1.9/modules/botnet/botnet.c

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.6 - (show annotations) (download) (as text)
Tue Nov 6 00:05:40 2007 UTC (11 years, 6 months ago) by sven
Branch: MAIN
CVS Tags: HEAD
Changes since 1.5: +73 -16 lines
File MIME type: text/x-chdr
 * Added a new socketfilter that provides a per socket timer for easy
   implementation of various timeouts.
 * All sockets that expect user logins now have a 60 second timeout for
   the user to supply a valid login.
 * All botnet sockets now have a 30 second timeout for the bot to do a
   successful login. After that it has a 90 second timeout after which
   a ping will be sent. After another 90 seconds the socket is closed.

1 /* botnet.c: support for linking with other bots
2 *
3 * Copyright (C) 2003, 2004 Eggheads Development Team
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20 #ifndef lint
21 static const char rcsid[] = "$Id: botnet.c,v 1.5 2007-10-27 19:55:51 sven Exp $";
22 #endif
23
24 #include <eggdrop/eggdrop.h>
25
26 #include "botnet.h"
27
28 EXPORT_SCOPE int botnet_LTX_start(egg_module_t *modinfo);
29
30 typedef struct {
31 char *ip;
32 int port;
33 } botnet_config_t;
34
35 static int bot_close(int why);
36 static int do_link(user_t *u, const char *text);
37
38 static int bot_on_delete(event_owner_t *owner, void *client_data);
39 //static int sock_on_delete(event_owner_t *owner, void *client_data);
40
41 /* Partyline commands. */
42 static int party_plus_bot(partymember_t *p, char *nick, user_t *u, char *cmd, char *text);
43 static int party_minus_bot(partymember_t *p, char *nick, user_t *u, char *cmd, char *text);
44
45 /* Sockbuf handler. */
46 static int idx_on_newclient(void *client_data, int idx, int newidx, const char *peer_ip, int peer_port);
47 static int idx_on_connect(void *client_data, int idx, const char *peer_ip, int peer_port);
48 static int idx_on_read(void *client_data, int idx, char *data, int len);
49 static int idx_on_eof(void *client_data, int idx, int err, const char *errmsg);
50 static int idx_on_delete(event_owner_t *owner, void *client_data);
51
52 static int got_bbroadcast(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len);
53 static int got_botmsg(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len);
54 static int got_bquit(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len);
55 static int got_broadcast(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len);
56 static int got_chanmsg(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len);
57 static int got_endlink(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len);
58 static int got_extension(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len);
59 static int got_join(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len);
60 static int got_link(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len);
61 static int got_login(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len);
62 static int got_newbot(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len);
63 static int got_nick(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len);
64 static int got_part(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len);
65 static int got_ping(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len);
66 static int got_pong(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len);
67 static int got_privmsg(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len);
68 static int got_quit(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len);
69 static int got_unlink(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len);
70
71 static struct {
72 char *cmd;
73 int source;
74 int min_argc;
75 int (*function)(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len);
76 } cmd_mapping[] = {
77 {"bbroadcast", ENTITY_BOT, 1, got_bbroadcast},
78 {"botmsg", ENTITY_BOT, 1, got_botmsg},
79 {"bquit", ENTITY_BOT, 0, got_bquit},
80 {"broadcast", 0, 1, got_broadcast},
81 {"chanmsg", 0, 2, got_chanmsg},
82 {"el", ENTITY_BOT, 0, got_endlink},
83 {"extension", 0, 2, got_extension},
84 {"join", ENTITY_PARTYMEMBER, 1, got_join},
85 {"link", 0, 2, got_link},
86 {"login", ENTITY_BOT, 4, got_login},
87 {"newbot", ENTITY_BOT, 4, got_newbot},
88 {"nick", ENTITY_PARTYMEMBER, 1, got_nick},
89 {"part", ENTITY_PARTYMEMBER, 1, got_part},
90 {"ping", ENTITY_BOT, 0, got_ping},
91 {"pong", ENTITY_BOT, 0, got_pong},
92 {"privmsg", 0, 2, got_privmsg},
93 {"quit", ENTITY_PARTYMEMBER, 0, got_quit},
94 {"unlink", 0, 2, got_unlink}
95 };
96
97 static int cmd_num = sizeof(cmd_mapping) / sizeof(cmd_mapping[0]);
98
99 static int listen_idx;
100
101 static botnet_config_t botnet_config;
102
103 static sockbuf_handler_t server_handler = {
104 "botnet server",
105 NULL, NULL, idx_on_newclient,
106 NULL, NULL
107 };
108
109 static config_var_t botnet_config_vars[] = {
110 {"my-ip", &botnet_config.ip, CONFIG_STRING},
111 {"port", &botnet_config.port, CONFIG_INT},
112 {0}
113 };
114
115 static event_owner_t bot_owner = {
116 "botnet", NULL,
117 NULL, NULL,
118 bot_on_delete
119 };
120
121 static event_owner_t sock_owner = {
122 "botnet", NULL,
123 NULL, NULL,
124 idx_on_delete
125 };
126
127 static event_owner_t generic_owner = {
128 "botnet", NULL,
129 NULL, NULL,
130 NULL
131 };
132
133 /*static event_owner_t sock_owner = {
134 "oldbotnet", NULL,
135 NULL, NULL,
136 sock_on_delete
137 };*/
138
139 static bind_list_t party_binds[] = {
140 {"n", "+bot", party_plus_bot},
141 {"n", "-bot", party_minus_bot},
142 {0}
143 };
144
145 static sockbuf_handler_t client_handler = {
146 "botnet",
147 idx_on_connect, idx_on_eof, NULL,
148 idx_on_read, NULL
149 };
150
151 /* +bot <bot> <host> <port> */
152 static int party_plus_bot(partymember_t *p, char *nick, user_t *u, char *cmd, char *text)
153 {
154 char *name, *host, *port;
155 user_t *bot;
156
157 egg_get_words(text, NULL, &name, &host, &port, NULL);
158 if (!port) {
159 partymember_printf(p, _("Syntax: +bot <bot> <host> <port>"));
160 goto done;
161 }
162
163 bot = user_new(name);
164 if (!bot) {
165 partymember_printf(p, _("Could not create bot '%s'."), name);
166 goto done;
167 }
168
169 user_set_flags_str(bot, NULL, "+b");
170 user_set_setting(bot, "bot", "type", "eggdrop");
171 user_set_setting(bot, "bot", "host", host);
172 user_set_setting(bot, "bot", "port", port);
173
174 done:
175 if (name) free(name);
176 if (host) free(host);
177 if (port) free(port);
178 return 0;
179 }
180
181 /* -bot <bot> */
182 static int party_minus_bot(partymember_t *p, char *nick, user_t *u, char *cmd, char *text)
183 {
184 char *type;
185 user_t *bot;
186
187 while (isspace(*text)) text++;
188
189 if (!text || !*text) {
190 partymember_printf(p, "Syntax: -bot <bot>");
191 return(0);
192 }
193
194 bot = user_lookup_by_handle(text);
195 if (!bot) {
196 partymember_printf(p, _("Could not find user '%s'."), text);
197 return(0);
198 }
199
200 user_get_setting(bot, "bot", "type", &type);
201 if (!type || !(bot->flags | USER_BOT) || strcmp(type, "eggdrop")) {
202 partymember_printf(p, _("Error: '%s' is not an eggdrop bot."), bot->handle);
203 return(0);
204 }
205
206 partymember_printf(p, _("Deleting user '%s'."), bot->handle);
207 user_delete(bot);
208 return(BIND_RET_LOG);
209 }
210
211 static int get_entity(botnet_entity_t *ent, char *text)
212 {
213 char *p;
214 int id = -1;
215 botnet_bot_t *bot;
216 partymember_t *pm;
217
218 p = strchr(text, '@');
219 if (p) {
220 *p = 0;
221 id = b64dec_int(text);
222 text = p + 1;
223 }
224 bot = botnet_lookup(text);
225 if (!bot && strcmp(text, botnet_get_name())) return 1;
226 if (id == -1) {
227 set_bot_entity(ent, bot);
228 return 0;
229 }
230 pm = partymember_lookup(NULL, bot, id);
231 if (!pm) return 1;
232 set_user_entity(ent, pm);
233 return 0;
234 }
235
236 static int do_link(user_t *user, const char *type)
237 {
238 char *host = NULL, *portstr = NULL, *password = NULL;
239 int port;
240 bot_t *data;
241
242 user_get_setting(user, NULL, "bot.host", &host);
243 user_get_setting(user, NULL, "bot.port", &portstr);
244 user_get_setting(user, NULL, "bot.password", &password);
245
246 if (portstr) port = atoi(portstr);
247 if (!host || !portstr || port <= 0 || port > 65535) {
248 putlog(LOG_MISC, "*", _("Error linking %s: Invalid telnet address:port stored."), user->handle);
249 return BIND_RET_BREAK;
250 }
251
252 data = malloc(sizeof(*data));
253 data->bot = NULL;
254 data->user = user;
255 data->idx = egg_connect(host, port, -1);
256 data->proto = NULL;
257 if (password) data->pass = strdup(password);
258 else data->pass = NULL;
259 data->incoming = 0;
260 data->linking = 1;
261 data->idle = 0;
262
263 sockbuf_set_handler(data->idx, &client_handler, data, &sock_owner);
264 netstring_on(data->idx);
265 socktimer_on(data->idx, 30, 0, NULL, NULL, &generic_owner);
266
267 putlog(LOG_MISC, "*", _("Linking to %s (%s %d) on idx %d."), user->handle, host, port, data->idx);
268 return BIND_RET_BREAK;
269 }
270
271 static void do_ping(int idx, void *client_data)
272 {
273 bot_t *bot = client_data;
274
275 if (bot->idle == -1) {
276 botnet_delete(bot->bot, _("Ping timeout"));
277 } else if (bot->idle == 0) {
278 bot->idle = 1;
279 } else {
280 bot->idle = -1;
281 egg_iprintf(bot->idx, "ping\n");
282 }
283 }
284
285 static int got_bbroadcast(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len)
286 {
287 if (argc <= 1) len = 0;
288 botnet_botbroadcast(src->bot, argv[0], argv[argc - 1], len);
289
290 return 0;
291 }
292
293 static int got_botmsg(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len)
294 {
295 botnet_entity_t dst;
296
297 if (get_entity(&dst, argv[0])) return 0;
298 if (dst.what != ENTITY_BOT) return 0;
299
300 if (argc <= 2) len = 0;
301 botnet_botmsg(src->bot, dst.bot, argv[1], argv[argc - 1], len);
302
303 return 0;
304 }
305
306 static int got_bquit(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len)
307 {
308 botnet_delete(src->bot, len ? argv[0] : "No reason");
309
310 return 0;
311 }
312
313 static int got_broadcast(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len)
314 {
315 botnet_broadcast(src, argv[0], len);
316
317 return 0;
318 }
319
320 static int got_chanmsg(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len)
321 {
322 partychan_msg_name(argv[0], src, argv[1], len);
323
324 return 0;
325 }
326
327 static int got_endlink(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len)
328 {
329 botnet_link_success(src->bot);
330
331 return 0;
332 }
333
334 static int got_extension(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len)
335 {
336 botnet_entity_t dst;
337
338 if (argc <= 2) len = 0;
339
340 if (argv[0][0] == '*') {
341 botnet_extension(EXTENSION_ALL, src, NULL, NULL, argv[1], argv[argc - 1], len);
342 }
343
344 if (get_entity(&dst, argv[0])) return 0;
345 if (dst.what != ENTITY_BOT) return 0;
346
347 botnet_extension(EXTENSION_ONE, src, dst.bot, NULL, argv[1], argv[argc - 1], len);
348
349 return 0;
350 }
351
352 /* login channel [netburst] */
353
354 static int got_join(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len)
355 {
356 int netburst = 0;
357
358 if (argc >= 2) netburst = b64dec_int(argv[1]) & 1;
359 partychan_join_name(argv[0], src->user, netburst);
360
361 return 0;
362 }
363
364 static int got_link(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len)
365 {
366 botnet_entity_t dst;
367
368 if (get_entity(&dst, argv[0])) return 0;
369 if (dst.what != ENTITY_BOT) return 0;
370
371 botnet_link(src, dst.bot, argv[1]);
372 return 0;
373 }
374
375 /* login nick ident host id */
376
377 static int got_login(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len)
378 {
379 partymember_new(b64dec_int(argv[3]), NULL, src->bot, argv[0], argv[1], argv[2], NULL, NULL, &generic_owner);
380 return 0;
381 }
382
383 /* newbot uplink name type version fullversion linking */
384
385 static int got_newbot(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len)
386 {
387 int flags = 0;
388 xml_node_t *info;
389 botnet_bot_t *new;
390
391 if (argc >= 5) flags = b64dec_int(argv[4]);
392
393 info = xml_node_new();
394 xml_node_set_str(argv[1], info, "type", 0, (void *) 0);
395 xml_node_set_int(b64dec_int(argv[2]), info, "numversion", 0, (void *) 0);
396 xml_node_set_str(argv[3], info, "version", 0, (void *) 0);
397
398 new = botnet_new(argv[0], NULL, src->bot, bot->bot, info, NULL, NULL, &generic_owner, flags & 1);
399 if (!new) {
400 botnet_delete(bot->bot, _("Couldn't create introduced bot"));
401 xml_node_delete(info);
402 return 0;
403 }
404
405 return 0;
406 }
407
408 static int got_nick(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len)
409 {
410 partymember_set_nick(src->user, argv[0]);
411 return 0;
412 }
413
414 static int got_part(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len)
415 {
416 char *reason = NULL;
417
418 if (argc >= 2) reason = argv[argc - 1];
419 partychan_part_name(argv[0], src->user, reason);
420
421 return 0;
422 }
423
424 static int got_ping(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len)
425 {
426 egg_iprintf(bot->idx, "pong\n");
427
428 return 0;
429 }
430
431 static int got_pong(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len)
432 {
433 return 0;
434 }
435
436 static int got_privmsg(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len)
437 {
438 partymember_t *dst;
439 botnet_entity_t ent;
440
441 if (get_entity(&ent, argv[0])) return 0;
442 if (ent.what != ENTITY_PARTYMEMBER) return 0;
443 dst = ent.user;
444 partymember_msg(dst, src, argv[1], len);
445 return 0;
446 }
447
448 static int got_quit(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len)
449 {
450 partymember_delete(src->user, NULL, len ? argv[0] : "No reason.");
451 return 0;
452 }
453
454 static int got_unlink(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len)
455 {
456 botnet_entity_t dst;
457
458 if (get_entity(&dst, argv[0])) return 0;
459 if (dst.what != ENTITY_BOT) return 0;
460
461 botnet_link(src, dst.bot, argv[1]);
462 return 0;
463 }
464
465 static int idx_on_newclient(void *client_data, int idx, int newidx, const char *peer_ip, int peer_port)
466 {
467 bot_t *session;
468
469 session = malloc(sizeof(*session));
470 session->bot = NULL;
471 session->user = NULL;
472 session->idx = newidx;
473 session->proto = NULL;
474 session->pass = NULL;
475 session->incoming = 1;
476 session->linking = 1;
477 session->idle = 0;
478
479 sockbuf_set_handler(newidx, &client_handler, session, &sock_owner);
480 netstring_on(newidx);
481 socktimer_on(newidx, 30, 0, NULL, NULL, &generic_owner);
482
483 return 0;
484 }
485
486 static int idx_on_connect(void *client_data, int idx, const char *peer_ip, int peer_port)
487 {
488 bot_t *bot = client_data;
489
490 // no special features yet
491 // egg_iprintf(idx, "proto para1 para2");
492 bot->proto = malloc(sizeof(*bot->proto));
493 bot->proto->dummy = 0;
494 egg_iprintf(idx, ":%s hello %s", botnet_get_name(), bot->user->handle);
495
496 return 0;
497 }
498
499 /*!
500 * \brief Handles the login for incomming links.
501 *
502 * \param bot The ::bot_t struct for this link.
503 * \param src The source of this message. This is a string!
504 * \param cmd The command.
505 * \param argc The number of parameters.
506 * \param argv Up to 20 parameters. NULL terminated.
507 * \param len The length of the last parameter.
508 *
509 * \return Always 0.
510 */
511
512 static int recving_login(bot_t *bot, char *src, char *cmd, int argc, char *argv[], int len) {
513 if (src) {
514 if (!bot->user) {
515 bot->user = user_lookup_by_handle(src);
516 if (!bot->user || !(bot->user->flags & USER_BOT) || !strcmp(src, botnet_get_name())) {
517 sockbuf_delete(bot->idx);
518 return 0;
519 }
520 if (botnet_lookup(src) || bot->user->flags & (USER_LINKING_BOT | USER_LINKED_BOT)) {
521 sockbuf_delete(bot->idx);
522 return 0;
523 }
524 } else {
525 if (src && strcmp(src, bot->user->handle)) {
526 sockbuf_delete(bot->idx);
527 return 0;
528 }
529 }
530 }
531 if (!strcasecmp(cmd, "PROTO")) {
532 if (bot->proto) {
533 sockbuf_delete(bot->idx);
534 return 0;
535 }
536 bot->proto = malloc(sizeof(*bot->proto));
537 bot->proto->dummy = 0;
538 egg_iprintf(bot->idx, "PROTO");
539 return 0;
540 }
541 if (!bot->user) {
542 sockbuf_delete(bot->idx);
543 return 0;
544 }
545 if (!bot->proto) {
546 bot->proto = malloc(sizeof(*bot->proto));
547 bot->proto->dummy = 0;
548 }
549
550 if (!strcasecmp(cmd, "HELLO")) {
551 int i;
552 char salt[33], *pass = NULL;
553 unsigned char hash[16];
554 MD5_CTX md5;
555
556 if (bot->pass || argc != 1 || strcmp(argv[0], botnet_get_name())) {
557 sockbuf_delete(bot->idx);
558 return 0;
559 }
560 user_get_setting(bot->user, NULL, "bot.password", &pass);
561 if (!pass || !*pass) {
562 egg_iprintf(bot->idx, "thisbot eggdrop %s %s %s :%s", botnet_get_name(), "1090000", "eggdrop1.9.0+cvs", "some informative stuff");
563 bot->pass = calloc(1, 1);
564 return 0;
565 }
566 for (i = 0; i < 32; ++i) {
567 salt[i] = random() % 62;
568 if (salt[i] < 26) salt[i] += 'A';
569 else if (salt[i] < 52) salt[i] += 'a' - 26;
570 else salt[i] += '0' - 52;
571 }
572 salt[32] = 0;
573 MD5_Init(&md5);
574 MD5_Update(&md5, salt, 32);
575 MD5_Update(&md5, pass, strlen(pass));
576 MD5_Final(hash, &md5);
577 bot->pass = malloc(33);
578 MD5_Hex(hash, bot->pass);
579 egg_iprintf(bot->idx, "passreq %s", salt);
580 } else if (!strcasecmp(cmd, "PASS")) {
581 if (!bot->pass || argc != 1 || strcmp(argv[0], bot->pass)) {
582 sockbuf_delete(bot->idx);
583 return 0;
584 }
585 *bot->pass = 0;
586 egg_iprintf(bot->idx, ":%s thisbot eggdrop %s %s :%s", botnet_get_name(), b64enc_int(1090000), "eggdrop1.9.0+cvs", "some informative stuff");
587 } else if (!strcasecmp(cmd, "THISBOT")) {
588 xml_node_t *info;
589
590 if (!bot->pass || *bot->pass || argc != 4) {
591 sockbuf_delete(bot->idx);
592 return 0;
593 }
594 free(bot->pass);
595 bot->pass = NULL;
596 bot->linking = 0;
597
598 info = xml_node_new();
599 xml_node_set_str(argv[0], info, "type", 0, (void *) 0);
600 xml_node_set_int(b64dec_int(argv[1]), info, "numversion", 0, (void *) 0);
601 xml_node_set_str(argv[2], info, "version", 0, (void *) 0);
602
603 bot->bot = botnet_new(bot->user->handle, bot->user, NULL, NULL, info, &bothandler, bot, &bot_owner, 0);
604 socktimer_on(bot->idx, 90, TIMER_REPEAT, do_ping, bot, &generic_owner);
605 botnet_replay_net(bot->bot);
606 egg_iprintf(bot->idx, "el");
607 } else {
608 sockbuf_delete(bot->idx);
609 }
610 return 0;
611 }
612
613 static int sending_login(bot_t *bot, char *src, char *cmd, int argc, char *argv[], int len)
614 {
615 if (src && strcmp(src, bot->user->handle)) {
616 egg_iprintf(bot->idx, "error :Wrong bot.");
617 sockbuf_delete(bot->idx);
618 return 0;
619 }
620 if (!strcasecmp(cmd, "PROTO")) {
621 if (bot->proto) {
622 egg_iprintf(bot->idx, "error :Been there, done that.");
623 sockbuf_delete(bot->idx);
624 return 0;
625 }
626 bot->proto = malloc(sizeof(*bot->proto));
627 bot->proto->dummy = 0;
628 egg_iprintf(bot->idx, ":%s hello %s", botnet_get_name(), bot->user->handle);
629 } else if (!strcasecmp(cmd, "PASSREQ")) {
630 char buf[33];
631 unsigned char hash[16];
632 MD5_CTX md5;
633 if (argc != 1 || !bot->proto || !bot->pass || !*bot->pass) {
634 if (!bot->pass) putlog(LOG_MISC, "*", "botnet error: password on %s needs to be reset.", bot->user->handle);
635 egg_iprintf(bot->idx, "error :Expected something else.");
636 sockbuf_delete(bot->idx);
637 return 0;
638 }
639 MD5_Init(&md5);
640 MD5_Update(&md5, argv[0], len);
641 MD5_Update(&md5, bot->pass, strlen(bot->pass));
642 MD5_Final(hash, &md5);
643 MD5_Hex(hash, buf);
644 egg_iprintf(bot->idx, "pass %s", buf);
645 *bot->pass = 0;
646 } else if (!strcasecmp(cmd, "THISBOT")) {
647 xml_node_t *info;
648
649 if (argc != 4) {
650 sockbuf_delete(bot->idx);
651 return 0;
652 }
653 egg_iprintf(bot->idx, ":%s thisbot eggdrop %s %s :%s", botnet_get_name(), b64enc_int(1090000), "eggdrop1.9.0+cvs", "some informative stuff");
654 free(bot->pass);
655 bot->pass = NULL;
656 bot->linking = 0;
657
658 info = xml_node_new();
659 xml_node_set_str(argv[0], info, "type", 0, (void *) 0);
660 xml_node_set_int(b64dec_int(argv[1]), info, "numversion", 0, (void *) 0);
661 xml_node_set_str(argv[2], info, "version", 0, (void *) 0);
662
663 bot->bot = botnet_new(bot->user->handle, bot->user, NULL, NULL, info, &bothandler, bot, &bot_owner, 0);
664 socktimer_on(bot->idx, 90, TIMER_REPEAT, do_ping, bot, &generic_owner);
665 botnet_replay_net(bot->bot);
666 egg_iprintf(bot->idx, "el");
667 } else {
668 sockbuf_delete(bot->idx);
669 }
670 return 0;
671 }
672
673 static int idx_on_read(void *client_data, int idx, char *data, int len)
674 {
675 int argc = 0;
676 char *start = data, *p, *srcstr = NULL, *argv[22];
677 bot_t *bot = client_data;
678 botnet_entity_t src;
679
680 if (!len) return 0;
681 if (*data == ':') {
682 srcstr = data + 1;
683 p = strchr(srcstr, ' ');
684 if (!p) return 0;
685 *p = 0;
686 data = p + 1;
687 while (isspace(*data)) ++data;
688 }
689
690 while (*data) {
691 argv[argc++] = data;
692 if (*data == ':') {
693 argv[argc - 1]++;
694 break;
695 }
696 if (argc == 21) break;
697 p = strchr(data, ' ');
698 if (!p) break;
699 *p = 0;
700 data = p + 1;
701 while (isspace(*data)) ++data;
702 }
703
704 if (!argc) return 0;
705
706 len -= argv[argc - 1] - start;
707 argv[argc] = NULL;
708
709 if (!strcasecmp(argv[0], "error")) {
710 putlog(LOG_MISC, "*", _("Botnet: Error from %s: %s"), bot->user ? bot->user->handle : "unknown", argv[1] ? argv[1] : "no reason");
711 if (bot->bot) botnet_delete(bot->bot, "Error from bot.");
712 else sockbuf_delete(bot->idx);
713 return 0;
714 }
715
716 if (!bot->bot) {
717 if (bot->incoming) return recving_login(bot, srcstr, argv[0], argc - 1, argv + 1, len);
718 else return sending_login(bot, srcstr, argv[0], argc - 1, argv + 1, len);
719 }
720
721 if (srcstr) {
722 char *at;
723 botnet_bot_t *srcbot;
724
725 at = strchr(srcstr, '@');
726 if (get_entity(&src, srcstr)) {
727 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);
728 else putlog(LOG_MISC, "*", _("Botnet: Desync! %s says %s came from %s who doesn't exist!"), bot->bot->name, argv[0], srcstr);
729 return 0;
730 }
731 if (src.what == ENTITY_BOT) srcbot = src.bot;
732 else srcbot = src.user->bot;
733 if (botnet_check_direction(bot->bot, srcbot)) return 0;
734 } else {
735 set_bot_entity(&src, bot->bot);
736 }
737
738 int min = 0, max = cmd_num - 1, cur = max / 2;
739 while (min <= max) {
740 int ret = strcasecmp(argv[0], cmd_mapping[cur].cmd);
741 if (!ret) {
742 if (argc < cmd_mapping[cur].min_argc) return 0;
743 if (cmd_mapping[cur].source && cmd_mapping[cur].source != src.what) return 0;
744 return cmd_mapping[cur].function(bot, &src, argv[0], argc - 1, argv + 1, len);
745 } else if (ret < 0) {
746 max = cur - 1;
747 } else {
748 min = cur + 1;
749 }
750 cur = (min + max) / 2;
751 }
752 putlog(LOG_MISC, "*", _("Botnet: Got unknown something from %s: %s"), bot->user->handle, argv[0]);
753 return 0;
754 }
755
756 static int idx_on_eof(void *client_data, int idx, int err, const char *errmsg)
757 {
758 bot_t *bot = client_data;
759
760 if (!bot->bot) {
761 if (!bot->incoming) {
762 if (bot->user->flags & USER_LINKING_BOT) botnet_link_failed(bot->user, errmsg ? errmsg : "no error");
763 bot->user = NULL; /* Might already be in the process of being reconnected, forget about it. */
764 }
765 sockbuf_delete(idx);
766 } else {
767 putlog(LOG_MISC, "*", _("eof from %s (%s)."), bot->bot->name, errmsg ? errmsg : "no error");
768 botnet_delete(bot->bot, errmsg ? errmsg : "eof");
769 }
770
771 return 0;
772 }
773
774 static int idx_on_delete(event_owner_t *owner, void *client_data)
775 {
776 bot_t *bot = client_data;
777
778 bot->idx = -1;
779 if (bot->bot) botnet_delete(bot->bot, _("Socket deleted."));
780 else if (!bot->incoming && bot->user && bot->user->flags & USER_LINKING_BOT) botnet_link_failed(bot->user, "Socket deleted.");
781
782 if (bot->pass) free(bot->pass);
783 free(bot);
784
785 return 0;
786 }
787
788 /*!
789 * \brief on_delete callback for ::botnet_bot_t.
790 *
791 * Gets called every time a directly linked bot created by this module is
792 * deleted. Marks it as deleted in the ::bot_t struct and deletes the
793 * ::sockbuf_t.
794 *
795 * \param owner The ::event_owner_t struct belonging to this bot. It's bot_owner.
796 * \param client_data Our callback data. The ::bot_t struct of the deleted bot.
797 * \return Always 0.
798 */
799
800 static int bot_on_delete(event_owner_t *owner, void *client_data)
801 {
802 bot_t *bot = client_data;
803
804 bot->bot = NULL;
805 if (bot->idx >= 0) sockbuf_delete(bot->idx);
806
807 return 0;
808 }
809
810 static void bot_init()
811 {
812 int real_port;
813 void *config_root;
814
815 botnet_config.port = 3333;
816
817 config_root = config_get_root("eggdrop");
818 config_link_table(botnet_config_vars, config_root, "botnet", 0, NULL);
819 config_update_table(botnet_config_vars, config_root, "botnet", 0, NULL);
820
821 listen_idx = egg_server(botnet_config.ip, botnet_config.port, &real_port);
822 sockbuf_set_handler(listen_idx, &server_handler, NULL, &generic_owner);
823
824 bind_add_simple(BTN_BOTNET_REQUEST_LINK, NULL, "eggdrop", do_link);
825 }
826
827 static int bot_close(int why)
828 {
829 void *config_root;
830
831 config_root = config_get_root("eggdrop");
832 config_unlink_table(botnet_config_vars, config_root, "botnet", 0, NULL);
833
834 sockbuf_delete(listen_idx);
835
836 bind_rem_simple(BTN_BOTNET_REQUEST_LINK, NULL, "eggdrop", do_link);
837
838 return 0;
839 }
840
841 int botnet_LTX_start(egg_module_t *modinfo)
842 {
843 bot_owner.module = sock_owner.module = generic_owner.module = modinfo;
844 modinfo->name = "botnet";
845 modinfo->author = "eggdev";
846 modinfo->version = "1.0.0";
847 modinfo->description = "botnet support";
848 modinfo->close_func = bot_close;
849
850 bot_init();
851
852 return 0;
853 }

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23