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

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

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


Revision 1.3 - (hide annotations) (download) (as text)
Tue Nov 23 16:36:23 2010 UTC (8 years, 7 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 simple 1.1 /*
2     * botcmd.c -- handles:
3     * commands that comes across the botnet
4     * userfile transfer and update commands from sharebots
5     *
6 pseudo 1.3 * $Id: botcmd.c,v 1.2 2010/10/19 12:13:32 pseudo Exp $
7 simple 1.1 */
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 pseudo 1.2 #ifdef TLS
36     extern int tls_vfybots;
37     extern int tls_vfyclients;
38     extern SSL_CTX *ssl_ctx;
39     #endif
40 simple 1.1 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 pseudo 1.2 #ifdef TLS
1455     /* Negotiate an encrypted session over the existing link
1456 pseudo 1.3 * starttls <c/s>
1457 pseudo 1.2 */
1458     static void bot_starttls(int idx, char *par)
1459     {
1460 pseudo 1.3 char *con;
1461 pseudo 1.2 /* We're already using ssl, ignore the request */
1462     if (dcc[idx].ssl)
1463     return;
1464    
1465 pseudo 1.3 con = newsplit(&par);
1466     /* check who's going to play the server */
1467     if (!egg_strcasecmp(con, "s")) { /* we're server */
1468 pseudo 1.2 putlog(LOG_BOTS, "*", "Got STARTTLS from %s. Replying...", dcc[idx].nick);
1469 pseudo 1.3 dprintf(idx, "starttls c\n");
1470 pseudo 1.2 ssl_handshake(dcc[idx].sock, TLS_LISTEN, tls_vfybots, LOG_BOTS,
1471     dcc[idx].host, NULL);
1472 pseudo 1.3 } 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 pseudo 1.2 }
1476     dcc[idx].ssl = 1;
1477     }
1478     #endif
1479    
1480 simple 1.1 /* 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 pseudo 1.2 #ifdef TLS
1566     {"starttls", (IntFunc) bot_starttls},
1567     #endif
1568 simple 1.1 {"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