/[cvs]/eggdrop1.8/src/botcmd.c
ViewVC logotype

Contents of /eggdrop1.8/src/botcmd.c

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


Revision 1.3 - (show annotations) (download) (as text)
Tue Nov 23 16:36:23 2010 UTC (8 years, 5 months ago) by pseudo
Branch: MAIN
CVS Tags: HEAD
Changes since 1.2: +10 -16 lines
File MIME type: text/x-chdr
Fixed a problem with sharing causing starttls to fail.
Moved STARTTLS early in the bot link process and synchronized the handshake.
Made it possible for ssl handshakes to complete even without data to be sent on the channel.
Fixed an ancient bug resulting in sending uninitialized strings when sharing bot addresses.
Enabled userfile sending over ssl.

1 /*
2 * botcmd.c -- handles:
3 * commands that comes across the botnet
4 * userfile transfer and update commands from sharebots
5 *
6 * $Id: botcmd.c,v 1.2 2010/10/19 12:13:32 pseudo Exp $
7 */
8 /*
9 * Copyright (C) 1997 Robey Pointer
10 * Copyright (C) 1999 - 2010 Eggheads Development Team
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 */
26
27 #include "main.h"
28 #include "tandem.h"
29 #include "users.h"
30 #include "chan.h"
31 #include "modules.h"
32
33 extern char botnetnick[], ver[], admin[], network[], motdfile[];
34 extern int dcc_total, remote_boots, noshare;
35 #ifdef TLS
36 extern int tls_vfybots;
37 extern int tls_vfyclients;
38 extern SSL_CTX *ssl_ctx;
39 #endif
40 extern struct dcc_t *dcc;
41 extern struct chanset_t *chanset;
42 extern struct userrec *userlist;
43 extern Tcl_Interp *interp;
44 extern time_t now, online_since;
45 extern party_t *party;
46 extern module_entry *module_list;
47
48 static char TBUF[1024]; /* Static buffer for goofy bot stuff */
49
50 static char base64to[256] = {
51 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
52 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
53 0, 0, 0, 0, 0, 0, 0, 0, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0,
54 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
55 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 62, 0, 63, 0, 0, 0, 26, 27, 28,
56 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
57 49, 50, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
58 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
59 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
60 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
61 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
62 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
63 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
64 };
65
66
67 int base64_to_int(char *buf)
68 {
69 int i = 0;
70
71 while (*buf) {
72 i = i << 6;
73 i += base64to[(int) *buf];
74 buf++;
75 }
76 return i;
77 }
78
79 /* Used for 1.0 compatibility: if a join message arrives with no sock#,
80 * i'll just grab the next "fakesock" # (incrementing to assure uniqueness)
81 */
82 static int fakesock = 2300;
83
84 static void fake_alert(int idx, char *item, char *extra)
85 {
86 static unsigned long lastfake; /* The last time fake_alert was used */
87
88 if (now - lastfake > 10) {
89 #ifndef NO_OLD_BOTNET
90 if (b_numver(idx) < NEAT_BOTNET)
91 dprintf(idx, "chat %s NOTICE: %s (%s != %s).\n",
92 botnetnick, NET_FAKEREJECT, item, extra);
93 else
94 #endif
95 dprintf(idx, "ct %s NOTICE: %s (%s != %s).\n",
96 botnetnick, NET_FAKEREJECT, item, extra);
97 putlog(LOG_BOTS, "*", "%s %s (%s != %s).", dcc[idx].nick, NET_FAKEREJECT,
98 item, extra);
99 lastfake = now;
100 }
101 }
102
103 /* chan <from> <chan> <text>
104 */
105 static void bot_chan2(int idx, char *msg)
106 {
107 char *from, *p, *s;
108 int i, chan;
109
110 if (bot_flags(dcc[idx].user) & BOT_ISOLATE)
111 return;
112 from = newsplit(&msg);
113 p = newsplit(&msg);
114 #ifndef NO_OLD_BOTNET
115 if (b_numver(idx) < NEAT_BOTNET)
116 chan = atoi(p);
117 else
118 #endif
119 chan = base64_to_int(p);
120 /* Strip annoying control chars */
121 for (p = s = from; *s; s++)
122 if ((*s > 31) && (*s != 127))
123 *p++ = *s;
124 if (*p)
125 *p = 0;
126 p = strchr(from, '@');
127 if (p) {
128 snprintf(TBUF, sizeof(TBUF), "<%s> %s", from, msg);
129 *p = 0;
130 if (!partyidle(p + 1, from)) {
131 *p = '@';
132 fake_alert(idx, "user", from);
133 return;
134 }
135 *p = '@';
136 p++;
137 } else {
138 sprintf(TBUF, "*** (%s) %s", from, msg);
139 p = from;
140 }
141 i = nextbot(p);
142 if (i != idx) {
143 fake_alert(idx, "direction", p);
144 } else {
145 chanout_but(-1, chan, "%s\n", TBUF);
146 /* Send to new version bots */
147 if (i >= 0)
148 botnet_send_chan(idx, from, NULL, chan, msg);
149 if (strchr(from, '@') != NULL)
150 check_tcl_chat(from, chan, msg);
151 else
152 check_tcl_bcst(from, chan, msg);
153 }
154 }
155
156 /* chat <from> <notice> -- only from bots
157 */
158 static void bot_chat(int idx, char *par)
159 {
160 char *from;
161 int i;
162
163 if (bot_flags(dcc[idx].user) & BOT_ISOLATE)
164 return;
165 from = newsplit(&par);
166 if (strchr(from, '@') != NULL) {
167 fake_alert(idx, "bot", from);
168 return;
169 }
170 /* Make sure the bot is valid */
171 i = nextbot(from);
172 if (i != idx) {
173 fake_alert(idx, "direction", from);
174 return;
175 }
176 chatout("*** (%s) %s\n", from, par);
177 botnet_send_chat(idx, from, par);
178 check_tcl_bcst(from, -1, par);
179 }
180
181 /* actchan <from> <chan> <text>
182 */
183 static void bot_actchan(int idx, char *par)
184 {
185 char *from, *p, *s;
186 int i, chan;
187
188 if (bot_flags(dcc[idx].user) & BOT_ISOLATE)
189 return;
190 from = newsplit(&par);
191 p = strchr(from, '@');
192 if (p == NULL) {
193 /* How can a bot do an action? */
194 fake_alert(idx, "user@bot", from);
195 return;
196 }
197 *p = 0;
198 if (!partyidle(p + 1, from)) {
199 *p = '@';
200 fake_alert(idx, "user", from);
201 return;
202 }
203 *p = '@';
204 p++;
205 i = nextbot(p);
206 if (i != idx) {
207 fake_alert(idx, "direction", p);
208 return;
209 }
210 p = newsplit(&par);
211 #ifndef NO_OLD_BOTNET
212 if (b_numver(idx) < NEAT_BOTNET)
213 chan = atoi(p);
214 else
215 #endif
216 chan = base64_to_int(p);
217 for (p = s = from; *s; s++)
218 if ((*s > 31) && (*s != 127))
219 *p++ = *s;
220 if (*p)
221 *p = 0;
222 chanout_but(-1, chan, "* %s %s\n", from, par);
223 botnet_send_act(idx, from, NULL, chan, par);
224 check_tcl_act(from, chan, par);
225 }
226
227 /* priv <from> <to> <message>
228 */
229 static void bot_priv(int idx, char *par)
230 {
231 char *from, *p, *to = TBUF, *tobot;
232 int i;
233
234 from = newsplit(&par);
235 tobot = newsplit(&par);
236 splitc(to, tobot, '@');
237 p = strchr(from, '@');
238 if (p != NULL)
239 p++;
240 else
241 p = from;
242 i = nextbot(p);
243 if (i != idx) {
244 fake_alert(idx, "direction", p);
245 return;
246 }
247 if (!to[0])
248 return; /* Silently ignore notes to '@bot' */
249 if (!egg_strcasecmp(tobot, botnetnick)) { /* For me! */
250 if (p == from)
251 add_note(to, from, par, -2, 0);
252 else {
253 i = add_note(to, from, par, -1, 0);
254 if (from[0] != '@')
255 switch (i) {
256 case NOTE_ERROR:
257 botnet_send_priv(idx, botnetnick, from, NULL,
258 "%s %s.", BOT_NOSUCHUSER, to);
259 break;
260 case NOTE_STORED:
261 botnet_send_priv(idx, botnetnick, from, NULL, "%s", BOT_NOTESTORED2);
262 break;
263 case NOTE_FULL:
264 botnet_send_priv(idx, botnetnick, from, NULL, "%s", BOT_NOTEBOXFULL);
265 break;
266 case NOTE_AWAY:
267 botnet_send_priv(idx, botnetnick, from, NULL,
268 "%s %s", to, BOT_NOTEISAWAY);
269 break;
270 case NOTE_FWD:
271 botnet_send_priv(idx, botnetnick, from, NULL,
272 "%s %s", "Not online; note forwarded to:", to);
273 break;
274 case NOTE_REJECT:
275 botnet_send_priv(idx, botnetnick, from, NULL,
276 "%s %s", to, "rejected your note.");
277 break;
278 case NOTE_TCL:
279 break; /* Do nothing */
280 case NOTE_OK:
281 botnet_send_priv(idx, botnetnick, from, NULL,
282 "%s %s.", BOT_NOTESENTTO, to);
283 break;
284 }
285 }
286 } else { /* Pass it on */
287 i = nextbot(tobot);
288 if (i >= 0)
289 botnet_send_priv(i, from, to, tobot, "%s", par);
290 }
291 }
292
293 static void bot_bye(int idx, char *par)
294 {
295 char s[1024];
296 int users, bots;
297
298 bots = bots_in_subtree(findbot(dcc[idx].nick));
299 users = users_in_subtree(findbot(dcc[idx].nick));
300 simple_sprintf(s, "%s %s. %s (lost %d bot%s and %d user%s)",
301 BOT_DISCONNECTED, dcc[idx].nick, par[0] ?
302 par : "No reason", bots, (bots != 1) ?
303 "s" : "", users, (users != 1) ? "s" : "");
304 putlog(LOG_BOTS, "*", "%s", s);
305 chatout("*** %s\n", s);
306 botnet_send_unlinked(idx, dcc[idx].nick, s);
307 dprintf(idx, "*bye\n");
308 killsock(dcc[idx].sock);
309 lostdcc(idx);
310 }
311
312 static void remote_tell_who(int idx, char *nick, int chan)
313 {
314 int i = 10, k, l, ok = 0;
315 char s[1024], *realnick;
316 struct chanset_t *c;
317
318 realnick = strchr(nick, ':');
319 if (realnick)
320 realnick++;
321 else
322 realnick = nick;
323 putlog(LOG_BOTS, "*", "#%s# who", realnick);
324 strcpy(s, "Channels: ");
325 for (c = chanset; c; c = c->next)
326 if (!channel_secret(c) && !channel_inactive(c)) {
327 l = strlen(c->dname);
328 if (i + l < 1021) {
329 if (i > 10)
330 sprintf(s, "%s, %s", s, c->dname);
331 else {
332 strcpy(s, c->dname);
333 i += (l + 2);
334 }
335 }
336 }
337 if (i > 10) {
338 botnet_send_priv(idx, botnetnick, nick, NULL, "%s (%s)", s, ver);
339 } else
340 botnet_send_priv(idx, botnetnick, nick, NULL, "%s (%s)", BOT_NOCHANNELS,
341 ver);
342 if (admin[0])
343 botnet_send_priv(idx, botnetnick, nick, NULL, "Admin: %s", admin);
344 if (chan == 0)
345 botnet_send_priv(idx, botnetnick, nick, NULL, "%s (* = owner, + = master,"
346 " %% = botmaster, @ = op, ^ = halfop)", BOT_PARTYMEMBS);
347 else {
348 simple_sprintf(s, "assoc %d", chan);
349 if ((Tcl_Eval(interp, s) != TCL_OK) || tcl_resultempty())
350 botnet_send_priv(idx, botnetnick, nick, NULL, "%s %s%d: (* = owner, + ="
351 " master, %% = botmaster, @ = op, ^ = halfop)\n",
352 BOT_PEOPLEONCHAN, (chan < GLOBAL_CHANS) ? "" : "*",
353 chan % GLOBAL_CHANS);
354 else
355 botnet_send_priv(idx, botnetnick, nick, NULL, "%s '%s' (%s%d): (* = "
356 "owner, + = master, %% = botmaster, @ = op, ^ = halfop)\n",
357 BOT_PEOPLEONCHAN, tcl_resultstring(), (chan < GLOBAL_CHANS) ?
358 "" : "*", chan % GLOBAL_CHANS);
359 }
360 for (i = 0; i < dcc_total; i++)
361 if (dcc[i].type->flags & DCT_REMOTEWHO)
362 if (dcc[i].u.chat->channel == chan) {
363 k = sprintf(s, " %c%-15s %s", (geticon(i) == '-' ? ' ' : geticon(i)),
364 dcc[i].nick, dcc[i].host);
365 if (now - dcc[i].timeval > 300) {
366 unsigned long days, hrs, mins;
367
368 days = (now - dcc[i].timeval) / 86400;
369 hrs = ((now - dcc[i].timeval) - (days * 86400)) / 3600;
370 mins = ((now - dcc[i].timeval) - (hrs * 3600)) / 60;
371 if (days > 0)
372 sprintf(s + k, " (%s %lud%luh)", MISC_IDLE, days, hrs);
373 else if (hrs > 0)
374 sprintf(s + k, " (%s %luh%lum)", MISC_IDLE, hrs, mins);
375 else
376 sprintf(s + k, " (%s %lum)", MISC_IDLE, mins);
377 }
378 botnet_send_priv(idx, botnetnick, nick, NULL, "%s", s);
379 if (dcc[i].u.chat->away != NULL)
380 botnet_send_priv(idx, botnetnick, nick, NULL, " %s: %s",
381 MISC_AWAY, dcc[i].u.chat->away);
382 }
383 for (i = 0; i < dcc_total; i++)
384 if (dcc[i].type == &DCC_BOT) {
385 if (!ok) {
386 ok = 1;
387 botnet_send_priv(idx, botnetnick, nick, NULL, "%s:", BOT_BOTSCONNECTED);
388 }
389 sprintf(s, " %s%c%-15s %s",
390 dcc[i].status & STAT_CALLED ? "<-" : "->",
391 dcc[i].status & STAT_SHARE ? '+' : ' ',
392 dcc[i].nick, dcc[i].u.bot->version);
393 botnet_send_priv(idx, botnetnick, nick, NULL, "%s", s);
394 }
395 ok = 0;
396 for (i = 0; i < dcc_total; i++)
397 if (dcc[i].type->flags & DCT_REMOTEWHO)
398 if (dcc[i].u.chat->channel != chan) {
399 if (!ok) {
400 ok = 1;
401 botnet_send_priv(idx, botnetnick, nick, NULL, "%s:", BOT_OTHERPEOPLE);
402 }
403 l = sprintf(s, " %c%-15s %s", (geticon(i) == '-' ? ' ' : geticon(i)),
404 dcc[i].nick, dcc[i].host);
405 if (now - dcc[i].timeval > 300) {
406 k = (now - dcc[i].timeval) / 60;
407 if (k < 60)
408 sprintf(s + l, " (%s %dm)", MISC_IDLE, k);
409 else
410 sprintf(s + l, " (%s %dh%dm)", MISC_IDLE, k / 60, k % 60);
411 }
412 botnet_send_priv(idx, botnetnick, nick, NULL, "%s", s);
413 if (dcc[i].u.chat->away != NULL)
414 botnet_send_priv(idx, botnetnick, nick, NULL,
415 " %s: %s", MISC_AWAY, dcc[i].u.chat->away);
416 }
417 }
418
419 /* who <from@bot> <tobot> <chan#>
420 */
421 static void bot_who(int idx, char *par)
422 {
423 char *from, *to, *p;
424 int i, chan;
425
426 from = newsplit(&par);
427 p = strchr(from, '@');
428 if (!p) {
429 sprintf(TBUF, "%s@%s", from, dcc[idx].nick);
430 from = TBUF;
431 }
432 to = newsplit(&par);
433 if (!egg_strcasecmp(to, botnetnick))
434 to[0] = 0;
435 #ifndef NO_OLD_BOTNET
436 if (b_numver(idx) < NEAT_BOTNET)
437 chan = atoi(par);
438 else
439 #endif
440 chan = base64_to_int(par);
441 if (to[0]) {
442 i = nextbot(to);
443 if (i >= 0)
444 botnet_send_who(i, from, to, chan);
445 } else
446 remote_tell_who(idx, from, chan);
447 }
448
449 static void bot_endlink(int idx, char *par)
450 {
451 dcc[idx].status &= ~STAT_LINKING;
452 }
453
454 /* info? <from@bot> -> send priv
455 */
456 static void bot_infoq(int idx, char *par)
457 {
458 char s[200], s2[32], *realnick;
459 struct chanset_t *chan;
460 time_t now2;
461 int hr, min;
462
463 /* Strip the idx from user@bot */
464 realnick = strchr(par, ':');
465 if (realnick)
466 realnick++;
467 else
468 realnick = par;
469 putlog(LOG_BOTS, "*", "#%s# botinfo", realnick);
470
471 now2 = now - online_since;
472 s2[0] = 0;
473 if (now2 > 86400) {
474 int days = now2 / 86400;
475
476 /* Days */
477 sprintf(s2, "%d day", days);
478 if (days >= 2)
479 strcat(s2, "s");
480 strcat(s2, ", ");
481 now2 -= days * 86400;
482 }
483 hr = (time_t) ((int) now2 / 3600);
484 now2 -= (hr * 3600);
485 min = (time_t) ((int) now2 / 60);
486 sprintf(&s2[strlen(s2)], "%02d:%02d", (int) hr, (int) min);
487 if (module_find("server", 0, 0)) {
488 s[0] = 0;
489 for (chan = chanset; chan; chan = chan->next) {
490 if (!channel_secret(chan)) {
491 if ((strlen(s) + strlen(chan->dname) + strlen(network)
492 + strlen(botnetnick) + strlen(ver) + 1) >= 200) {
493 strcat(s, "++ ");
494 break; /* Yegads..! */
495 }
496 strcat(s, chan->dname);
497 strcat(s, ", ");
498 }
499 }
500 if (s[0]) {
501 s[strlen(s) - 2] = 0;
502 botnet_send_priv(idx, botnetnick, par, NULL,
503 "%s <%s> (%s) [UP %s]", ver, network, s, s2);
504 } else
505 botnet_send_priv(idx, botnetnick, par, NULL, "%s <%s> (%s) [UP %s]", ver,
506 network, BOT_NOCHANNELS, s2);
507 } else
508 botnet_send_priv(idx, botnetnick, par, NULL,
509 "%s <NO_IRC> [UP %s]", ver, s2);
510 botnet_send_infoq(idx, par);
511 }
512
513 static void bot_ping(int idx, char *par)
514 {
515 botnet_send_pong(idx);
516 }
517
518 static void bot_pong(int idx, char *par)
519 {
520 dcc[idx].status &= ~STAT_PINGED;
521 }
522
523 /* link <from@bot> <who> <to-whom>
524 */
525 static void bot_link(int idx, char *par)
526 {
527 char *from, *bot, *rfrom;
528 int i;
529
530 from = newsplit(&par);
531 bot = newsplit(&par);
532
533 if (!egg_strcasecmp(bot, botnetnick)) {
534 if ((rfrom = strchr(from, ':')))
535 rfrom++;
536 else
537 rfrom = from;
538 putlog(LOG_CMDS, "*", "#%s# link %s", rfrom, par);
539 if (botlink(from, -1, par))
540 botnet_send_priv(idx, botnetnick, from, NULL, "%s %s ...",
541 BOT_LINKATTEMPT, par);
542 else
543 botnet_send_priv(idx, botnetnick, from, NULL, "%s.", BOT_CANTLINKTHERE);
544 } else {
545 i = nextbot(bot);
546 if (i >= 0)
547 botnet_send_link(i, from, bot, par);
548 }
549 }
550
551 /* unlink <from@bot> <linking-bot> <undesired-bot> <reason>
552 */
553 static void bot_unlink(int idx, char *par)
554 {
555 char *from, *bot, *rfrom, *p, *undes;
556 int i;
557
558 from = newsplit(&par);
559 bot = newsplit(&par);
560 undes = newsplit(&par);
561 if (!egg_strcasecmp(bot, botnetnick)) {
562 if ((rfrom = strchr(from, ':')))
563 rfrom++;
564 else
565 rfrom = from;
566 putlog(LOG_CMDS, "*", "#%s# unlink %s (%s)", rfrom, undes, par[0] ? par :
567 "No reason");
568 i = botunlink(-3, undes, par[0] ? par : NULL, rfrom);
569 if (i == 1) {
570 p = strchr(from, '@');
571 if (p) {
572 /* idx will change after unlink -- get new idx
573 *
574 * TODO: This has changed with the new lostdcc() behaviour. Check
575 * if we can optimise the situation.
576 */
577 i = nextbot(p + 1);
578 if (i >= 0)
579 botnet_send_priv(i, botnetnick, from, NULL,
580 "Unlinked from %s.", undes);
581 }
582 } else if (i == 0) {
583 botnet_send_unlinked(-1, undes, "");
584 p = strchr(from, '@');
585 if (p) {
586 /* Ditto above, about idx */
587 i = nextbot(p + 1);
588 if (i >= 0)
589 botnet_send_priv(i, botnetnick, from, NULL,
590 "%s %s.", BOT_CANTUNLINK, undes);
591 }
592 } else {
593 p = strchr(from, '@');
594 if (p) {
595 i = nextbot(p + 1);
596 if (i >= 0)
597 botnet_send_priv(i, botnetnick, from, NULL,
598 "Can't remotely unlink sharebots.");
599 }
600 }
601 } else {
602 i = nextbot(bot);
603 if (i >= 0)
604 botnet_send_unlink(i, from, bot, undes, par);
605 }
606 }
607
608 /* Bot next share?
609 */
610 static void bot_update(int idx, char *par)
611 {
612 char *bot, x;
613 int vnum;
614
615 bot = newsplit(&par);
616 x = par[0];
617 if (x)
618 par++;
619 #ifndef NO_OLD_BOTNET
620 if (b_numver(idx) < NEAT_BOTNET)
621 vnum = atoi(par);
622 else
623 #endif
624 vnum = base64_to_int(par);
625 if (in_chain(bot))
626 updatebot(idx, bot, x, vnum);
627 }
628
629 /* Newbot next share?
630 */
631 static void bot_nlinked(int idx, char *par)
632 {
633 char *newbot, *next, *p, s[1024], x;
634 int bogus = 0, i;
635 struct userrec *u;
636
637 newbot = newsplit(&par);
638 next = newsplit(&par);
639 s[0] = 0;
640 if (!next[0]) {
641 putlog(LOG_BOTS, "*", "Invalid eggnet protocol from %s (zapfing)",
642 dcc[idx].nick);
643 simple_sprintf(s, "%s %s (%s)", MISC_DISCONNECTED, dcc[idx].nick,
644 MISC_INVALIDBOT);
645 dprintf(idx, "error invalid eggnet protocol for 'nlinked'\n");
646 } else if ((in_chain(newbot)) || (!egg_strcasecmp(newbot, botnetnick))) {
647 /* Loop! */
648 putlog(LOG_BOTS, "*", "%s %s (mutual: %s)",
649 BOT_LOOPDETECT, dcc[idx].nick, newbot);
650 simple_sprintf(s, "%s %s: disconnecting %s", MISC_LOOP, newbot,
651 dcc[idx].nick);
652 dprintf(idx, "error Loop (%s)\n", newbot);
653 }
654 if (!s[0]) {
655 for (p = newbot; *p; p++)
656 if ((*p < 32) || (*p == 127) || ((p - newbot) >= HANDLEN))
657 bogus = 1;
658 i = nextbot(next);
659 if (i != idx)
660 bogus = 1;
661 }
662 if (bogus) {
663 putlog(LOG_BOTS, "*", "%s %s! (%s -> %s)", BOT_BOGUSLINK, dcc[idx].nick,
664 next, newbot);
665 simple_sprintf(s, "%s: %s %s", BOT_BOGUSLINK, dcc[idx].nick,
666 MISC_DISCONNECTED);
667 dprintf(idx, "error %s (%s -> %s)\n", BOT_BOGUSLINK, next, newbot);
668 }
669 if (bot_flags(dcc[idx].user) & BOT_LEAF) {
670 putlog(LOG_BOTS, "*", "%s %s (%s %s)",
671 BOT_DISCONNLEAF, dcc[idx].nick, newbot, BOT_LINKEDTO);
672 simple_sprintf(s, "%s %s (to %s): %s",
673 BOT_ILLEGALLINK, dcc[idx].nick, newbot, MISC_DISCONNECTED);
674 dprintf(idx, "error %s\n", BOT_YOUREALEAF);
675 }
676 if (s[0]) {
677 chatout("*** %s\n", s);
678 botnet_send_unlinked(idx, dcc[idx].nick, s);
679 dprintf(idx, "bye %s\n", BOT_ILLEGALLINK);
680 killsock(dcc[idx].sock);
681 lostdcc(idx);
682 return;
683 }
684 x = par[0];
685 if (x)
686 par++;
687 else
688 x = '-';
689 #ifndef NO_OLD_BOTNET
690 if (b_numver(idx) < NEAT_BOTNET)
691 i = atoi(par);
692 else
693 #endif
694 i = base64_to_int(par);
695 botnet_send_nlinked(idx, newbot, next, x, i);
696 if (x == '!') {
697 chatout("*** (%s) %s %s.\n", next, NET_LINKEDTO, newbot);
698 x = '-';
699 }
700 addbot(newbot, dcc[idx].nick, next, x, i);
701 check_tcl_link(newbot, next);
702 u = get_user_by_handle(userlist, newbot);
703 if (bot_flags(u) & BOT_REJECT) {
704 botnet_send_reject(idx, botnetnick, NULL, newbot, NULL, NULL);
705 putlog(LOG_BOTS, "*", "%s %s %s %s", BOT_REJECTING,
706 newbot, MISC_FROM, dcc[idx].nick);
707 }
708 }
709
710 #ifndef NO_OLD_BOTNET
711 static void bot_linked(int idx, char *par)
712 {
713 char s[1024];
714 int bots, users;
715
716 bots = bots_in_subtree(findbot(dcc[idx].nick));
717 users = users_in_subtree(findbot(dcc[idx].nick));
718 putlog(LOG_BOTS, "*", "%s", BOT_OLDBOT);
719 simple_sprintf(s, "%s %s (%s) (lost %d bot%s and %d user%s",
720 MISC_DISCONNECTED, dcc[idx].nick, MISC_OUTDATED,
721 bots, (bots != 1) ? "s" : "", users, (users != 1) ? "s" : "");
722 chatout("*** %s\n", s);
723 botnet_send_unlinked(idx, dcc[idx].nick, s);
724 killsock(dcc[idx].sock);
725 lostdcc(idx);
726 }
727 #endif /* !NO_OLD_BOTNET */
728
729 static void bot_unlinked(int idx, char *par)
730 {
731 int i;
732 char *bot;
733
734 bot = newsplit(&par);
735 i = nextbot(bot);
736 if ((i >= 0) && (i != idx)) /* Bot is NOT downstream along idx, so
737 * BOGUS! */
738 fake_alert(idx, "direction", bot);
739 else if (i >= 0) { /* Valid bot downstream of idx */
740 if (par[0])
741 chatout("*** (%s) %s\n", lastbot(bot), par);
742 botnet_send_unlinked(idx, bot, par);
743 unvia(idx, findbot(bot));
744 rembot(bot);
745 }
746 /* Otherwise it's not even a valid bot, so just ignore! */
747 }
748
749 /* trace <from@bot> <dest> <chain:chain..>
750 */
751 static void bot_trace(int idx, char *par)
752 {
753 char *from, *dest;
754 int i;
755
756 from = newsplit(&par);
757 dest = newsplit(&par);
758 simple_sprintf(TBUF, "%s:%s", par, botnetnick);
759 botnet_send_traced(idx, from, TBUF);
760 if (egg_strcasecmp(dest, botnetnick) && ((i = nextbot(dest)) > 0))
761 botnet_send_trace(i, from, dest, par);
762 }
763
764 /* traced <to@bot> <chain:chain..>
765 */
766 static void bot_traced(int idx, char *par)
767 {
768 char *to, *p;
769 int i, sock;
770
771 to = newsplit(&par);
772 p = strchr(to, '@');
773 if (p == NULL)
774 p = to;
775 else {
776 *p = 0;
777 p++;
778 }
779 if (!egg_strcasecmp(p, botnetnick)) {
780 time_t t = 0;
781 char *p = par, *ss = TBUF;
782
783 splitc(ss, to, ':');
784 if (ss[0])
785 sock = atoi(ss);
786 else
787 sock = -1;
788 if (par[0] == ':') {
789 t = atoi(par + 1);
790 p = strchr(par + 1, ':');
791 if (p)
792 p++;
793 else
794 p = par + 1;
795 }
796 for (i = 0; i < dcc_total; i++)
797 if ((dcc[i].type->flags & DCT_CHAT) &&
798 (!egg_strcasecmp(dcc[i].nick, to)) &&
799 ((sock == -1) || (sock == dcc[i].sock))) {
800 if (t) {
801 int j = 0;
802
803 {
804 register char *c = p;
805
806 for (; *c != '\0'; c++)
807 if (*c == ':')
808 j++;
809 }
810 dprintf(i, "%s -> %s (%lu secs, %d hop%s)\n", BOT_TRACERESULT, p,
811 now - t, j, (j != 1) ? "s" : "");
812 } else
813 dprintf(i, "%s -> %s\n", BOT_TRACERESULT, p);
814 }
815 } else {
816 i = nextbot(p);
817 if (p != to)
818 *--p = '@';
819 if (i >= 0)
820 botnet_send_traced(i, to, par);
821 }
822 }
823
824 /* reject <from> <bot>
825 */
826 static void bot_reject(int idx, char *par)
827 {
828 char *from, *who, *destbot, *frombot;
829 struct userrec *u;
830 int i;
831
832 if (bot_flags(dcc[idx].user) & BOT_ISOLATE)
833 return;
834 from = newsplit(&par);
835 frombot = strchr(from, '@');
836 if (frombot)
837 frombot++;
838 else
839 frombot = from;
840 i = nextbot(frombot);
841 if (i != idx) {
842 fake_alert(idx, "direction", frombot);
843 return;
844 }
845 who = newsplit(&par);
846 if (!(destbot = strchr(who, '@'))) {
847 /* Rejecting a bot */
848 i = nextbot(who);
849 if (i < 0) {
850 botnet_send_priv(idx, botnetnick, from, NULL, "%s %s (%s)",
851 BOT_CANTUNLINK, who, BOT_DOESNTEXIST);
852 } else if (!egg_strcasecmp(dcc[i].nick, who)) {
853 char s[1024];
854
855 /* I'm the connection to the rejected bot */
856 putlog(LOG_BOTS, "*", "%s %s %s", from, MISC_REJECTED, dcc[i].nick);
857 dprintf(i, "bye %s\n", par[0] ? par : MISC_REJECTED);
858 simple_sprintf(s, "%s %s (%s: %s)",
859 MISC_DISCONNECTED, dcc[i].nick, from,
860 par[0] ? par : MISC_REJECTED);
861 chatout("*** %s\n", s);
862 botnet_send_unlinked(i, dcc[i].nick, s);
863 killsock(dcc[i].sock);
864 lostdcc(i);
865 } else {
866 if (i >= 0)
867 botnet_send_reject(i, from, NULL, who, NULL, par);
868 }
869 } else { /* Rejecting user */
870 *destbot++ = 0;
871 if (!egg_strcasecmp(destbot, botnetnick)) {
872 /* Kick someone here! */
873 int ok = 0;
874
875 if (remote_boots == 1) {
876 frombot = strchr(from, '@');
877 if (frombot == NULL)
878 frombot = from;
879 else
880 frombot++;
881 u = get_user_by_handle(userlist, frombot);
882 if (!(bot_flags(u) & BOT_SHARE)) {
883 add_note(from, botnetnick, "No non sharebot boots.", -1, 0);
884 ok = 1;
885 }
886 } else if (remote_boots == 0) {
887 botnet_send_priv(idx, botnetnick, from, NULL, "%s", BOT_NOREMOTEBOOT);
888 ok = 1;
889 }
890 for (i = 0; (i < dcc_total) && (!ok); i++)
891 if ((!egg_strcasecmp(who, dcc[i].nick)) &&
892 (dcc[i].type->flags & DCT_CHAT)) {
893 u = get_user_by_handle(userlist, dcc[i].nick);
894 if (u && (u->flags & USER_OWNER)) {
895 add_note(from, botnetnick, BOT_NOOWNERBOOT, -1, 0);
896 return;
897 }
898 do_boot(i, from, par);
899 ok = 1;
900 putlog(LOG_CMDS, "*", "#%s# boot %s (%s)", from, who,
901 par[0] ? par : "No reason");
902 }
903 } else {
904 i = nextbot(destbot);
905 *--destbot = '@';
906 if (i >= 0)
907 botnet_send_reject(i, from, NULL, who, NULL, par);
908 }
909 }
910 }
911
912 static void bot_thisbot(int idx, char *par)
913 {
914 if (egg_strcasecmp(par, dcc[idx].nick)) {
915 char s[1024];
916
917 putlog(LOG_BOTS, "*", NET_WRONGBOT, dcc[idx].nick, par);
918 dprintf(idx, "bye %s\n", MISC_IMPOSTER);
919 simple_sprintf(s, "%s %s (%s)", MISC_DISCONNECTED, dcc[idx].nick,
920 MISC_IMPOSTER);
921 chatout("*** %s\n", s);
922 botnet_send_unlinked(idx, dcc[idx].nick, s);
923 unvia(idx, findbot(dcc[idx].nick));
924 killsock(dcc[idx].sock);
925 lostdcc(idx);
926 return;
927 }
928 if (bot_flags(dcc[idx].user) & BOT_LEAF)
929 dcc[idx].status |= STAT_LEAF;
930 /* Set capitalization the way they want it */
931 noshare = 1;
932 change_handle(dcc[idx].user, par);
933 noshare = 0;
934 strcpy(dcc[idx].nick, par);
935 }
936
937 static void bot_handshake(int idx, char *par)
938 {
939 struct userrec *u = get_user_by_handle(userlist, dcc[idx].nick);
940
941 /* We *don't* want botnet passwords migrating */
942 noshare = 1;
943 set_user(&USERENTRY_PASS, u, par);
944 noshare = 0;
945 }
946
947 /* Used to send a direct msg from Tcl on one bot to Tcl on another
948 * zapf <frombot> <tobot> <code [param]>
949 */
950 static void bot_zapf(int idx, char *par)
951 {
952 char *from, *to;
953 int i;
954
955 from = newsplit(&par);
956 to = newsplit(&par);
957 i = nextbot(from);
958 if (i != idx) {
959 fake_alert(idx, "direction", from);
960 return;
961 }
962 if (!egg_strcasecmp(to, botnetnick)) {
963 /* For me! */
964 char *opcode;
965
966 opcode = newsplit(&par);
967 check_tcl_bot(from, opcode, par);
968 return;
969 }
970 i = nextbot(to);
971 if (i >= 0)
972 botnet_send_zapf(i, from, to, par);
973 }
974
975 /* Used to send a global msg from Tcl on one bot to every other bot
976 * zapf-broad <frombot> <code [param]>
977 */
978 static void bot_zapfbroad(int idx, char *par)
979 {
980 char *from, *opcode;
981 int i;
982
983 from = newsplit(&par);
984 opcode = newsplit(&par);
985
986 i = nextbot(from);
987 if (i != idx) {
988 fake_alert(idx, "direction", from);
989 return;
990 }
991 check_tcl_bot(from, opcode, par);
992 botnet_send_zapf_broad(idx, from, opcode, par);
993 }
994
995 /* Show motd to someone
996 */
997 static void bot_motd(int idx, char *par)
998 {
999 FILE *vv;
1000 char *s = TBUF, *who, *p;
1001 int i;
1002 struct flag_record fr = { FR_BOT, USER_BOT, 0, 0, 0, 0 };
1003
1004 who = newsplit(&par);
1005 if (!par[0] || !egg_strcasecmp(par, botnetnick)) {
1006 int irc = 0;
1007
1008 p = strchr(who, ':');
1009 if (p)
1010 p++;
1011 else
1012 p = who;
1013 if (who[0] == '!') {
1014 irc = HELP_IRC;
1015 fr.global |=USER_HIGHLITE;
1016
1017 who++;
1018 } else if (who[0] == '#') {
1019 fr.global |=USER_HIGHLITE;
1020
1021 who++;
1022 }
1023 putlog(LOG_CMDS, "*", "#%s# motd", p);
1024 vv = fopen(motdfile, "r");
1025 if (vv != NULL) {
1026 botnet_send_priv(idx, botnetnick, who, NULL, "--- %s\n", MISC_MOTDFILE);
1027 help_subst(NULL, NULL, 0, irc, NULL);
1028 while (!feof(vv)) {
1029 fgets(s, 120, vv);
1030 if (!feof(vv)) {
1031 if (s[strlen(s) - 1] == '\n')
1032 s[strlen(s) - 1] = 0;
1033 if (!s[0])
1034 strcpy(s, " ");
1035 help_subst(s, who, &fr, HELP_DCC, dcc[idx].nick);
1036 if (s[0])
1037 botnet_send_priv(idx, botnetnick, who, NULL, "%s", s);
1038 }
1039 }
1040 fclose(vv);
1041 } else
1042 botnet_send_priv(idx, botnetnick, who, NULL, "%s :(", MISC_NOMOTDFILE);
1043 } else {
1044 /* Pass it on */
1045 i = nextbot(par);
1046 if (i >= 0)
1047 botnet_send_motd(i, who, par);
1048 }
1049 }
1050
1051 /* These are still here, so that they will pass the relevant
1052 * requests through even if no filesys is loaded.
1053 *
1054 * filereject <bot:filepath> <sock:nick@bot> <reason...>
1055 */
1056 static void bot_filereject(int idx, char *par)
1057 {
1058 char *path, *to, *tobot, *p;
1059 int i;
1060
1061 path = newsplit(&par);
1062 to = newsplit(&par);
1063 if ((tobot = strchr(to, '@')))
1064 tobot++;
1065 else
1066 tobot = to; /* Bot wants a file?! :) */
1067 if (egg_strcasecmp(tobot, botnetnick)) { /* for me! */
1068 p = strchr(to, ':');
1069 if (p != NULL) {
1070 *p = 0;
1071 for (i = 0; i < dcc_total; i++) {
1072 if (dcc[i].sock == atoi(to))
1073 dprintf(i, "%s (%s): %s\n", BOT_XFERREJECTED, path, par);
1074 }
1075 *p = ':';
1076 }
1077 /* No ':'? malformed */
1078 putlog(LOG_FILES, "*", "%s %s: %s", path, MISC_REJECTED, par);
1079 } else { /* Pass it on */
1080 i = nextbot(tobot);
1081 if (i >= 0)
1082 botnet_send_filereject(i, path, to, par);
1083 }
1084 }
1085
1086 /* filereq <sock:nick@bot> <bot:file>
1087 */
1088 static void bot_filereq(int idx, char *tobot)
1089 {
1090 char *from, *path;
1091 int i;
1092
1093 from = newsplit(&tobot);
1094 if ((path = strchr(tobot, ':'))) {
1095 *path++ = 0;
1096
1097 if (!egg_strcasecmp(tobot, botnetnick)) { /* For me! */
1098 /* Process this */
1099 module_entry *fs = module_find("filesys", 0, 0);
1100
1101 if (fs == NULL)
1102 botnet_send_priv(idx, botnetnick, from, NULL, MOD_NOFILESYSMOD);
1103 else {
1104 Function f = fs->funcs[FILESYS_REMOTE_REQ];
1105
1106 f(idx, from, path);
1107 }
1108 } else { /* Pass it on */
1109 i = nextbot(tobot);
1110 if (i >= 0)
1111 botnet_send_filereq(i, from, tobot, path);
1112 }
1113 }
1114 }
1115
1116 /* filesend <bot:path> <sock:nick@bot> <IP#> <port> <size>
1117 */
1118 static void bot_filesend(int idx, char *par)
1119 {
1120 char *botpath, *to, *tobot, *nick;
1121 int i;
1122 char *nfn;
1123
1124 botpath = newsplit(&par);
1125 to = newsplit(&par);
1126 if ((tobot = strchr(to, '@'))) {
1127 *tobot = 0;
1128 tobot++;
1129 } else
1130 tobot = to;
1131 if (!egg_strcasecmp(tobot, botnetnick)) { /* For me! */
1132 nfn = strrchr(botpath, '/');
1133 if (nfn == NULL) {
1134 nfn = strrchr(botpath, ':');
1135 if (nfn == NULL)
1136 nfn = botpath; /* That's odd. */
1137 else
1138 nfn++;
1139 } else
1140 nfn++;
1141 if ((nick = strchr(to, ':')))
1142 nick++;
1143 else
1144 nick = to;
1145 /* Send it to 'nick' as if it's from me */
1146 dprintf(DP_SERVER, "PRIVMSG %s :\001DCC SEND %s %s\001\n", nick, nfn, par);
1147 } else {
1148 i = nextbot(tobot);
1149 if (i >= 0) {
1150 *--tobot = '@';
1151 botnet_send_filesend(i, botpath, to, par);
1152 }
1153 }
1154 }
1155
1156 static void bot_error(int idx, char *par)
1157 {
1158 putlog(LOG_MISC | LOG_BOTS, "*", "%s: %s", dcc[idx].nick, par);
1159 }
1160
1161 /* nc <bot> <sock> <newnick>
1162 */
1163 static void bot_nickchange(int idx, char *par)
1164 {
1165 char *bot, *ssock, *newnick;
1166 int sock, i;
1167
1168 if (bot_flags(dcc[idx].user) & BOT_ISOLATE)
1169 return;
1170 bot = newsplit(&par);
1171 #ifndef NO_OLD_BOTNET
1172 if (b_numver(idx) < NEAT_BOTNET) {
1173 fake_alert(idx, "botversion", "NEAT_BOTNET");
1174 return;
1175 }
1176 #endif
1177 i = nextbot(bot);
1178 if (i != idx) {
1179 fake_alert(idx, "direction", bot);
1180 return;
1181 }
1182 ssock = newsplit(&par);
1183 sock = base64_to_int(ssock);
1184 newnick = newsplit(&par);
1185 i = partynick(bot, sock, newnick);
1186 if (i < 0) {
1187 fake_alert(idx, "sock#", ssock);
1188 return;
1189 }
1190 chanout_but(-1, party[i].chan, "*** (%s) Nick change: %s -> %s\n",
1191 bot, newnick, party[i].nick);
1192 botnet_send_nkch_part(idx, i, newnick);
1193 }
1194
1195 /* join <bot> <nick> <chan> <flag><sock> <from>
1196 */
1197 static void bot_join(int idx, char *par)
1198 {
1199 char *bot, *nick, *x, *y;
1200 struct userrec *u;
1201 int i, sock, chan, i2, linking = 0;
1202
1203 if (bot_flags(dcc[idx].user) & BOT_ISOLATE)
1204 return;
1205 bot = newsplit(&par);
1206 #ifndef NO_OLD_BOTNET
1207 if (b_numver(idx) >= NEAT_BOTNET)
1208 #endif
1209 if (bot[0] == '!') {
1210 linking = 1;
1211 bot++;
1212 }
1213 if (b_status(idx) & STAT_LINKING) {
1214 linking = 1;
1215 }
1216 nick = newsplit(&par);
1217 x = newsplit(&par);
1218 #ifndef NO_OLD_BOTNET
1219 if (b_numver(idx) < NEAT_BOTNET)
1220 chan = atoi(x);
1221 else
1222 #endif
1223 chan = base64_to_int(x);
1224 y = newsplit(&par);
1225 if ((chan < 0) || !y[0])
1226 return; /* Woops! pre 1.2.1's send .chat off'ers
1227 * too!! */
1228 if (!y[0]) {
1229 y[0] = '-';
1230 sock = 0;
1231 } else {
1232 #ifndef NO_OLD_BOTNET
1233 if (b_numver(idx) < NEAT_BOTNET)
1234 sock = atoi(y + 1);
1235 else
1236 #endif
1237 sock = base64_to_int(y + 1);
1238 }
1239 /* 1.1 bots always send a sock#, even on a channel change
1240 * so if sock# is 0, this is from an old bot and we must tread softly
1241 * grab old sock# if there is one, otherwise make up one.
1242 */
1243 if (sock == 0)
1244 sock = partysock(bot, nick);
1245 if (sock == 0)
1246 sock = fakesock++;
1247 i = nextbot(bot);
1248 if (i != idx) { /* Ok, garbage from a 1.0g (who uses that
1249 * now?) OR raistlin being evil :) */
1250 fake_alert(idx, "direction", bot);
1251 return;
1252 }
1253 u = get_user_by_handle(userlist, nick);
1254 if (u) {
1255 sprintf(TBUF, "@%s", bot);
1256 touch_laston(u, TBUF, now);
1257 }
1258 i = addparty(bot, nick, chan, y[0], sock, par, &i2);
1259 botnet_send_join_party(idx, linking, i2, i);
1260 if (i != chan) {
1261 if (i >= 0) {
1262 if (b_numver(idx) >= NEAT_BOTNET)
1263 chanout_but(-1, i, "*** (%s) %s %s %s.\n", bot, nick, NET_LEFTTHE,
1264 i ? "channel" : "party line");
1265 check_tcl_chpt(bot, nick, sock, i);
1266 }
1267 if ((b_numver(idx) >= NEAT_BOTNET) && !linking)
1268 chanout_but(-1, chan, "*** (%s) %s %s %s.\n", bot, nick, NET_JOINEDTHE,
1269 chan ? "channel" : "party line");
1270 check_tcl_chjn(bot, nick, chan, y[0], sock, par);
1271 }
1272 }
1273
1274 /* part <bot> <nick> <sock> [etc..]
1275 */
1276 static void bot_part(int idx, char *par)
1277 {
1278 char *bot, *nick, *etc;
1279 struct userrec *u;
1280 int sock, partyidx;
1281 int silent = 0;
1282
1283 if (bot_flags(dcc[idx].user) & BOT_ISOLATE)
1284 return;
1285 bot = newsplit(&par);
1286 if (bot[0] == '!') {
1287 silent = 1;
1288 bot++;
1289 }
1290 nick = newsplit(&par);
1291 etc = newsplit(&par);
1292 #ifndef NO_OLD_BOTNET
1293 if (b_numver(idx) < NEAT_BOTNET) {
1294 sock = atoi(etc);
1295 silent = 1;
1296 } else
1297 #endif
1298 sock = base64_to_int(etc);
1299 if (sock == 0)
1300 sock = partysock(bot, nick);
1301 u = get_user_by_handle(userlist, nick);
1302 if (u) {
1303 sprintf(TBUF, "@%s", bot);
1304 touch_laston(u, TBUF, now);
1305 }
1306 if ((partyidx = getparty(bot, sock)) != -1) {
1307 if (party[partyidx].chan >= 0)
1308 check_tcl_chpt(bot, nick, sock, party[partyidx].chan);
1309 if ((b_numver(idx) >= NEAT_BOTNET) && !silent) {
1310 register int chan = party[partyidx].chan;
1311
1312 if (par[0])
1313 chanout_but(-1, chan, "*** (%s) %s %s %s (%s).\n", bot, nick,
1314 NET_LEFTTHE, chan ? "channel" : "party line", par);
1315 else
1316 chanout_but(-1, chan, "*** (%s) %s %s %s.\n", bot, nick,
1317 NET_LEFTTHE, chan ? "channel" : "party line");
1318 }
1319 botnet_send_part_party(idx, partyidx, par, silent);
1320 remparty(bot, sock);
1321 }
1322 }
1323
1324 /* away <bot> <sock> <message>
1325 * null message = unaway
1326 */
1327 static void bot_away(int idx, char *par)
1328 {
1329 char *bot, *etc;
1330 int sock, partyidx, linking = 0;
1331
1332 if (bot_flags(dcc[idx].user) & BOT_ISOLATE)
1333 return;
1334 bot = newsplit(&par);
1335 #ifndef NO_OLD_BOTNET
1336 if (b_numver(idx) >= NEAT_BOTNET)
1337 #endif
1338 if (bot[0] == '!') {
1339 linking = 1;
1340 bot++;
1341 }
1342 if (b_status(idx) & STAT_LINKING) {
1343 linking = 1;
1344 }
1345 etc = newsplit(&par);
1346 #ifndef NO_OLD_BOTNET
1347 if (b_numver(idx) < NEAT_BOTNET)
1348 sock = atoi(etc);
1349 else
1350 #endif
1351 sock = base64_to_int(etc);
1352 if (sock == 0)
1353 sock = partysock(bot, etc);
1354 check_tcl_away(bot, sock, par);
1355 if (par[0]) {
1356 partystat(bot, sock, PLSTAT_AWAY, 0);
1357 partyaway(bot, sock, par);
1358 } else
1359 partystat(bot, sock, 0, PLSTAT_AWAY);
1360 partyidx = getparty(bot, sock);
1361 if ((b_numver(idx) >= NEAT_BOTNET) && !linking) {
1362 if (par[0])
1363 chanout_but(-1, party[partyidx].chan,
1364 "*** (%s) %s %s: %s.\n", bot,
1365 party[partyidx].nick, NET_AWAY, par);
1366 else
1367 chanout_but(-1, party[partyidx].chan,
1368 "*** (%s) %s %s.\n", bot, party[partyidx].nick, NET_UNAWAY);
1369 }
1370 botnet_send_away(idx, bot, sock, par, linking);
1371 }
1372
1373 /* (a courtesy info to help during connect bursts)
1374 * idle <bot> <sock> <#secs> [away msg]
1375 */
1376 static void bot_idle(int idx, char *par)
1377 {
1378 char *bot, *work;
1379 int sock, idle;
1380
1381 if (bot_flags(dcc[idx].user) & BOT_ISOLATE)
1382 return;
1383 bot = newsplit(&par);
1384 work = newsplit(&par);
1385 #ifndef NO_OLD_BOTNET
1386 if (b_numver(idx) < NEAT_BOTNET)
1387 sock = atoi(work);
1388 else
1389 #endif
1390 sock = base64_to_int(work);
1391 if (sock == 0)
1392 sock = partysock(bot, work);
1393 work = newsplit(&par);
1394 #ifndef NO_OLD_BOTNET
1395 if (b_numver(idx) < NEAT_BOTNET)
1396 idle = atoi(work);
1397 else
1398 #endif
1399 idle = base64_to_int(work);
1400 partysetidle(bot, sock, idle);
1401 if (par[0]) {
1402 partystat(bot, sock, PLSTAT_AWAY, 0);
1403 partyaway(bot, sock, par);
1404 }
1405 botnet_send_idle(idx, bot, sock, idle, par);
1406 }
1407
1408 #ifndef NO_OLD_BOTNET
1409
1410 static void bot_ufno(int idx, char *par)
1411 {
1412 putlog(LOG_BOTS, "*", "%s %s: %s", USERF_REJECTED, dcc[idx].nick, par);
1413 dcc[idx].status &= ~STAT_OFFERED;
1414 if (!(dcc[idx].status & STAT_GETTING))
1415 dcc[idx].status &= ~STAT_SHARE;
1416 }
1417
1418 static void bot_old_userfile(int idx, char *par)
1419 {
1420 putlog(LOG_BOTS, "*", "%s %s", USERF_OLDSHARE, dcc[idx].nick);
1421 dprintf(idx, "uf-no %s\n", USERF_ANTIQUESHARE);
1422 }
1423
1424 #endif /* !NO_OLD_BOTNET */
1425
1426 void bot_share(int idx, char *par)
1427 {
1428 sharein(idx, par);
1429 }
1430
1431 /* v <frombot> <tobot> <idx:nick>
1432 */
1433 static void bot_versions(int sock, char *par)
1434 {
1435 char *frombot = newsplit(&par), *tobot, *from;
1436 module_entry *me;
1437
1438 if (nextbot(frombot) != sock)
1439 fake_alert(sock, "versions-direction", frombot);
1440 else if (egg_strcasecmp(tobot = newsplit(&par), botnetnick)) {
1441 if ((sock = nextbot(tobot)) >= 0)
1442 dprintf(sock, "v %s %s %s\n", frombot, tobot, par);
1443 } else {
1444 from = newsplit(&par);
1445 botnet_send_priv(sock, botnetnick, from, frombot, "Modules loaded:\n");
1446 for (me = module_list; me; me = me->next)
1447 botnet_send_priv(sock, botnetnick, from, frombot,
1448 " Module: %s (v%d.%d)\n", me->name, me->major,
1449 me->minor);
1450 botnet_send_priv(sock, botnetnick, from, frombot, "End of module list.\n");
1451 }
1452 }
1453
1454 #ifdef TLS
1455 /* Negotiate an encrypted session over the existing link
1456 * starttls <c/s>
1457 */
1458 static void bot_starttls(int idx, char *par)
1459 {
1460 char *con;
1461 /* We're already using ssl, ignore the request */
1462 if (dcc[idx].ssl)
1463 return;
1464
1465 con = newsplit(&par);
1466 /* check who's going to play the server */
1467 if (!egg_strcasecmp(con, "s")) { /* we're server */
1468 putlog(LOG_BOTS, "*", "Got STARTTLS from %s. Replying...", dcc[idx].nick);
1469 dprintf(idx, "starttls c\n");
1470 ssl_handshake(dcc[idx].sock, TLS_LISTEN, tls_vfybots, LOG_BOTS,
1471 dcc[idx].host, NULL);
1472 } else { /* we're client, don't reply or we'll be in the loop forever */
1473 ssl_handshake(dcc[idx].sock, TLS_CONNECT, tls_vfybots, LOG_BOTS,
1474 dcc[idx].host, NULL);
1475 }
1476 dcc[idx].ssl = 1;
1477 }
1478 #endif
1479
1480 /* BOT COMMANDS
1481 *
1482 * function call should be:
1483 * int bot_whatever(idx,"parameters");
1484 *
1485 * SORT these, dcc_bot uses a shortcut which requires them sorted
1486 *
1487 * yup, those are tokens there to allow a more efficient botnet as
1488 * time goes on (death to slowly upgrading llama's)
1489 */
1490 botcmd_t C_bot[] =
1491 {
1492 {"a", (IntFunc) bot_actchan},
1493 #ifndef NO_OLD_BOTNET
1494 {"actchan", (IntFunc) bot_actchan},
1495 #endif
1496 {"aw", (IntFunc) bot_away},
1497 {"away", (IntFunc) bot_away},
1498 {"bye", (IntFunc) bot_bye},
1499 {"c", (IntFunc) bot_chan2},
1500 #ifndef NO_OLD_BOTNET
1501 {"chan", (IntFunc) bot_chan2},
1502 {"chat", (IntFunc) bot_chat},
1503 #endif
1504 {"ct", (IntFunc) bot_chat},
1505 {"e", (IntFunc) bot_error},
1506 {"el", (IntFunc) bot_endlink},
1507 #ifndef NO_OLD_BOTNET
1508 {"error", (IntFunc) bot_error},
1509 #endif
1510 {"f!", (IntFunc) bot_filereject},
1511 #ifndef NO_OLD_BOTNET
1512 {"filereject", (IntFunc) bot_filereject},
1513 {"filereq", (IntFunc) bot_filereq},
1514 {"filesend", (IntFunc) bot_filesend},
1515 #endif
1516 {"fr", (IntFunc) bot_filereq},
1517 {"fs", (IntFunc) bot_filesend},
1518 {"h", (IntFunc) bot_handshake},
1519 #ifndef NO_OLD_BOTNET
1520 {"handshake", (IntFunc) bot_handshake},
1521 #endif
1522 {"i", (IntFunc) bot_idle},
1523 {"i?", (IntFunc) bot_infoq},
1524 #ifndef NO_OLD_BOTNET
1525 {"idle", (IntFunc) bot_idle},
1526 {"info?", (IntFunc) bot_infoq},
1527 #endif
1528 {"j", (IntFunc) bot_join},
1529 #ifndef NO_OLD_BOTNET
1530 {"join", (IntFunc) bot_join},
1531 #endif
1532 {"l", (IntFunc) bot_link},
1533 #ifndef NO_OLD_BOTNET
1534 {"link", (IntFunc) bot_link},
1535 {"linked", (IntFunc) bot_linked},
1536 #endif
1537 {"m", (IntFunc) bot_motd},
1538 #ifndef NO_OLD_BOTNET
1539 {"motd", (IntFunc) bot_motd},
1540 #endif
1541 {"n", (IntFunc) bot_nlinked},
1542 {"nc", (IntFunc) bot_nickchange},
1543 #ifndef NO_OLD_BOTNET
1544 {"nlinked", (IntFunc) bot_nlinked},
1545 #endif
1546 {"p", (IntFunc) bot_priv},
1547 #ifndef NO_OLD_BOTNET
1548 {"part", (IntFunc) bot_part},
1549 #endif
1550 {"pi", (IntFunc) bot_ping},
1551 #ifndef NO_OLD_BOTNET
1552 {"ping", (IntFunc) bot_ping},
1553 #endif
1554 {"po", (IntFunc) bot_pong},
1555 #ifndef NO_OLD_BOTNET
1556 {"pong", (IntFunc) bot_pong},
1557 {"priv", (IntFunc) bot_priv},
1558 #endif
1559 {"pt", (IntFunc) bot_part},
1560 {"r", (IntFunc) bot_reject},
1561 #ifndef NO_OLD_BOTNET
1562 {"reject", (IntFunc) bot_reject},
1563 #endif
1564 {"s", (IntFunc) bot_share},
1565 #ifdef TLS
1566 {"starttls", (IntFunc) bot_starttls},
1567 #endif
1568 {"t", (IntFunc) bot_trace},
1569 {"tb", (IntFunc) bot_thisbot},
1570 {"td", (IntFunc) bot_traced},
1571 #ifndef NO_OLD_BOTNET
1572 {"thisbot", (IntFunc) bot_thisbot},
1573 {"trace", (IntFunc) bot_trace},
1574 {"traced", (IntFunc) bot_traced},
1575 #endif
1576 {"u", (IntFunc) bot_update},
1577 #ifndef NO_OLD_BOTNET
1578 {"uf-no", (IntFunc) bot_ufno},
1579 #endif
1580 {"ul", (IntFunc) bot_unlink},
1581 {"un", (IntFunc) bot_unlinked},
1582 #ifndef NO_OLD_BOTNET
1583 {"unaway", (IntFunc) bot_away},
1584 {"unlink", (IntFunc) bot_unlink},
1585 {"unlinked", (IntFunc) bot_unlinked},
1586 {"update", (IntFunc) bot_update},
1587 {"userfile?", (IntFunc) bot_old_userfile},
1588 #endif
1589 {"v", (IntFunc) bot_versions},
1590 {"w", (IntFunc) bot_who},
1591 #ifndef NO_OLD_BOTNET
1592 {"who", (IntFunc) bot_who},
1593 #endif
1594 {"z", (IntFunc) bot_zapf},
1595 #ifndef NO_OLD_BOTNET
1596 {"zapf", (IntFunc) bot_zapf},
1597 {"zapf-broad", (IntFunc) bot_zapfbroad},
1598 #endif
1599 {"zb", (IntFunc) bot_zapfbroad},
1600 {NULL, NULL}
1601 };

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23