/* botcmd.c -- handles: commands that comes across the botnet userfile transfer and update commands from sharebots dprintf'ized, 10nov95 */ /* This file is part of the eggdrop source code copyright (c) 1997 Robey Pointer and is distributed according to the GNU general public license. For full details, read the top of 'main.c' or the file called COPYING that was distributed with this code. */ #if HAVE_CONFIG_H #include #endif #include #include #include #include #include "eggdrop.h" #include "tandem.h" #include "users.h" #include "chan.h" #include "proto.h" #include "tclegg.h" extern tand_t tand[]; extern int tands; extern char botnetnick[]; extern int dcc_total; extern struct dcc_t dcc[]; extern int noshare; extern int passive; extern int share_users; extern char motdfile[]; extern struct userrec *userlist; extern char ver[]; extern char os[]; extern struct chanset_t *chanset; extern int serv; extern char ban_time; extern char ignore_time; extern char network[]; /* static buffer for goofy bot stuff */ char TBUF[1024]; /* used for 1.0 compatibility: if a join message arrives with no sock#, */ /* i'll just grab the next "fakesock" # (incrementing to assure uniqueness) */ int fakesock=2300; void fake_alert PROTO1(int,idx) { tprintf(dcc[idx].sock,"chat %s NOTICE: Fake message rejected.\n", botnetnick); } /* chan */ void bot_chan PROTO2(int,idx,char *,par) { char *from=TBUF,*s=TBUF+512,*p; int i,chan; nsplit(from,par); chan=atoi(par); nsplit(NULL,par); /* strip annoying control chars */ for (p=from; *p; ) { if ((*p<32) || (*p==127)) strcpy(p,p+1); else p++; } p=strchr(from,'@'); if (p==NULL) { sprintf(s,"*** (%s) %s",from,par); p=from; } else { sprintf(s,"<%s> %s",from,par); *p=0; partyidle(p+1,from); *p='@'; p++; } i=nextbot(p); if (i!=idx) { fake_alert(idx); return; } tandout_but(idx,"chan %s %d %s\n",from,chan,par); chanout(chan,"%s\n",s); if (strchr(from,'@')!=NULL) check_tcl_chat(from,chan,par); else check_tcl_bcst(from,chan,par); } /* chat -- only from bots */ void bot_chat PROTO2(int,idx,char *,par) { char *from=TBUF; int i; nsplit(from,par); if (strchr(from,'@')!=NULL) { fake_alert(idx); return; } /* make sure the bot is valid */ i=nextbot(from); if (i!=idx) { fake_alert(idx); return; } chatout("*** (%s) %s\n",from,par); tandout_but(idx,"chat %s %s\n",from,par); } /* actchan */ void bot_actchan PROTO2(int,idx,char *,par) { char *from=TBUF,*p; int i,chan; nsplit(from,par); p=strchr(from,'@'); if (p==NULL) { /* how can a bot do an action? */ fake_alert(idx); return; } *p=0; partyidle(p+1,from); *p='@'; p++; i=nextbot(p); if (i!=idx) { fake_alert(idx); return; } chan=atoi(par); nsplit(NULL,par); chanout(chan,"* %s %s\n",from,par); check_tcl_act(from,chan,par); tandout_but(idx,"actchan %s %d %s\n",from,chan,par); } /* priv */ void bot_priv PROTO2(int,idx,char *,par) { char *from=TBUF,*p,*to=TBUF+600,*tobot=TBUF+512; int i; nsplit(from,par); nsplit(tobot,par); tobot[40]=0; splitc(to,tobot,'@'); p=strchr(from,'@'); if (p!=NULL) p++; else p=from; i=nextbot(p); if ((i!=idx) || (!to[0])) { fake_alert(idx); return; } if (strcasecmp(tobot,botnetnick)==0) { /* for me! */ if (p==from) add_note(to,from,par,-2,0); else { i=add_note(to,from,par,-1,0); switch(i) { case NOTE_ERROR: tprintf(dcc[idx].sock,"priv %s %s No such user %s.\n",botnetnick, from,to); break; case NOTE_STORED: tprintf(dcc[idx].sock,"priv %s %s Not online; note stored.\n", botnetnick,from); break; case NOTE_FULL: tprintf(dcc[idx].sock,"priv %s %s Notebox is full, sorry.\n", botnetnick,from); break; case NOTE_AWAY: tprintf(dcc[idx].sock,"priv %s %s %s is away; note stored.\n", botnetnick,from,to); break; case NOTE_TCL: break; /* do nothing */ case NOTE_OK: tprintf(dcc[idx].sock,"priv %s %s Note sent to %s.\n",botnetnick, from,to); break; } } } else { /* pass it on */ i=nextbot(tobot); if (i>=0) tprintf(dcc[i].sock,"priv %s %s@%s %s\n",from,to,tobot,par); } } void bot_bye PROTO2(int,idx,char *,par) { putlog(LOG_BOTS,"*","Disconnected from: %s",dcc[idx].nick); chatout("*** Disconnected from: %s\n",dcc[idx].nick); tandout_but(idx,"unlinked %s\n",dcc[idx].nick); tandout_but(idx,"chat %s Disconnected from: %s\n",botnetnick,dcc[idx].nick); cancel_user_xfer(idx); rembot(dcc[idx].nick,dcc[idx].nick); unvia(idx,dcc[idx].nick); tprintf(dcc[idx].sock,"*bye\n"); killsock(dcc[idx].sock); lostdcc(idx); } /* who */ void bot_who PROTO2(int,idx,char *,par) { char *p; char *from=TBUF,*to=TBUF+512; int i; nsplit(from,par); p=strchr(from,'@'); if (p==NULL) { sprintf(to,"%s@%s",from,dcc[idx].nick); strcpy(from,to); } nsplit(to,par); if (strcasecmp(to,botnetnick)==0) to[0]=0; /* (for me) */ if (to[0]) { /* pass it on */ i=nextbot(to); if (i>=0) tprintf(dcc[i].sock,"who %s %s %s\n",from,to,par); } else { remote_tell_who(dcc[idx].sock,from,atoi(par)); } } void bot_version PROTO2(int,idx,char *,par) { strcpy(dcc[idx].u.bot->version,par); if ((share_users) && (get_attr_handle(dcc[idx].nick)&BOT_SHARE)) { if (passive) { if (dcc[idx].u.bot->status&STAT_CALLED) { if (can_resync(dcc[idx].nick)) tprintf(dcc[idx].sock,"resync?\n"); else tprintf(dcc[idx].sock,"userfile?\n"); dcc[idx].u.bot->status|=STAT_OFFERED; } } else { if (can_resync(dcc[idx].nick)) tprintf(dcc[idx].sock,"resync?\n"); else tprintf(dcc[idx].sock,"userfile?\n"); dcc[idx].u.bot->status|=STAT_OFFERED; } } } /* who? -> whom */ void bot_whoq PROTO2(int,idx,char *,par) { /* ignore old-style 'whom' request */ putlog(LOG_BOTS,"*","Outdated 'whom' request from %s (ignoring)", dcc[idx].nick); } /* info? -> send priv */ void bot_infoq PROTO2(int,idx,char *,par) { #ifndef NO_IRC char s[161]; struct chanset_t *chan; chan=chanset; s[0]=0; while (chan!=NULL) { if (!(chan->stat & CHAN_SECRET)) { strcat(s,chan->name); strcat(s,", "); } chan=chan->next; } if (s[0]) { s[strlen(s)-2]=0; tprintf(dcc[idx].sock,"priv %s %s %s <%s> (%s)\n",botnetnick,par,ver, network,s); } else tprintf(dcc[idx].sock,"priv %s %s %s <%s> (no channels)\n",botnetnick,par, ver,network); #else tprintf(dcc[idx].sock,"priv %s %s %s\n",botnetnick,par,ver); #endif tandout_but(idx,"info? %s\n",par); } /* whom */ void bot_whom PROTO2(int,idx,char *,par) { /* scrap it */ putlog(LOG_BOTS,"*","Outdated 'whom' request from %s (ignoring)", dcc[idx].nick); } void bot_ping PROTO2(int,idx,char *,par) { tprintf(dcc[idx].sock,"pong\n"); } void bot_pong PROTO2(int,idx,char *,par) { dcc[idx].u.bot->status&=~STAT_PINGED; } /* link */ void bot_link PROTO2(int,idx,char *,par) { char *from=TBUF,*bot=TBUF+512,*rfrom=TBUF+41; int i; nsplit(from,par); nsplit(bot,par); from[40]=0; if (strcasecmp(bot,botnetnick)==0) { strcpy(rfrom,from); splitc(NULL,rfrom,':'); putlog(LOG_CMDS,"*","#%s# link %s",rfrom,par); if (botlink(from,-2,par)) tprintf(dcc[idx].sock,"priv %s %s Attempting link to %s ...\n", botnetnick,from,par); else tprintf(dcc[idx].sock,"priv %s %s Can't link there.\n",botnetnick, from); } else { i=nextbot(bot); if (i>=0) tprintf(dcc[i].sock,"link %s %s %s\n",from,bot,par); } } /* unlink */ void bot_unlink PROTO2(int,idx,char *,par) { char *from=TBUF,*bot=TBUF+512,*rfrom=TBUF+41;int i; char *p; char *undes=TBUF+550; nsplit(from,par); nsplit(bot,par); nsplit(undes,par); from[40]=0; if (strcasecmp(bot,botnetnick)==0) { strcpy(rfrom,from); splitc(NULL,rfrom,':'); putlog(LOG_CMDS,"*","#%s# unlink %s (%s)",rfrom,undes,par[0]?par: "No reason"); if (botunlink(-2,undes,par[0]?par:NULL)) { p=strchr(from,'@'); if (p!=NULL) { /* idx will change after unlink -- get new idx */ i=nextbot(p+1); if (i>=0) tprintf(dcc[i].sock,"priv %s %s Unlinked %s.\n",botnetnick, from,undes); } } else { tandout("unlinked %s\n",undes); /* just to clear trash from link lists */ p=strchr(from,'@'); if (p!=NULL) { /* ditto above, about idx */ i=nextbot(p+1); if (i>=0) tprintf(dcc[i].sock,"priv %s %s Can't unlink %s.\n", botnetnick,from,undes); } } } else { i=nextbot(bot); if (i>=0) tprintf(dcc[i].sock,"unlink %s %s %s %s\n",from,bot,undes,par); } } void bot_ufno PROTO2(int,idx,char *,par) { putlog(LOG_BOTS,"*","User file rejected by %s: %s",dcc[idx].nick,par); dcc[idx].u.bot->status&=~STAT_OFFERED; if (!(dcc[idx].u.bot->status&STAT_GETTING)) dcc[idx].u.bot->status&=~STAT_SHARE; } void bot_ufobsolete PROTO2(int,idx,char *,par) { putlog(LOG_BOTS,"*","Can't send userfile to %s -- doesn't recognize new format", dcc[idx].nick); dcc[idx].u.bot->status&=~STAT_OFFERED; if (!(dcc[idx].u.bot->status&STAT_GETTING)) dcc[idx].u.bot->status&=~STAT_SHARE; /* drop the bot */ tprintf(dcc[idx].sock,"error Please upgrade; I can no longer send a userfile to you.\n"); tprintf(dcc[idx].sock,"bye\n"); tandout_but(idx,"unlinked %s\n",dcc[idx].nick); tandout_but(idx,"chat %s Disconnected %s (incompatible userfile transfer)\n", botnetnick,dcc[idx].nick); chatout("*** Disconnected %s (incompatible userfile transfer)\n", dcc[idx].nick); rembot(dcc[idx].nick,dcc[idx].nick); unvia(idx,dcc[idx].nick); killsock(dcc[idx].sock); lostdcc(idx); } void bot_ufyes3 PROTO2(int,idx,char *,par) { if (dcc[idx].u.bot->status&STAT_OFFERED) { dcc[idx].u.bot->status&=~STAT_OFFERED; dcc[idx].u.bot->status|=STAT_SHARE; dcc[idx].u.bot->status|=STAT_SENDING; start_sending_users(idx); putlog(LOG_BOTS,"*","Sending user file to %s",dcc[idx].nick); } } void bot_userfileq PROTO2(int,idx,char *,par) { int ok=1,i; flush_tbuf(dcc[idx].nick); if (!share_users) tprintf(dcc[idx].sock,"uf-no Not sharing userfile.\n"); else if (!passive) tprintf(dcc[idx].sock,"uf-no Aggressive mode active.\n"); else if (!(get_attr_handle(dcc[idx].nick) & BOT_SHARE)) tprintf(dcc[idx].sock,"uf-no You are not +s for me.\n"); else { for (i=0; istatus&STAT_SHARE) && (dcc[i].u.bot->status&STAT_GETTING)) ok=0; if (!ok) tprintf(dcc[idx].sock,"uf-no Already downloading a userfile.\n"); else { tprintf(dcc[idx].sock,"uf-yes3\n"); /* set stat-getting to avoid race condition (robey 23jun96) */ dcc[idx].u.bot->status|=STAT_SHARE|STAT_GETTING; putlog(LOG_BOTS,"*","Downloading user file from %s",dcc[idx].nick); } } } /* ufsend */ void bot_ufsend PROTO2(int,idx,char *,par) { char *ip=TBUF,*port=TBUF+512; int i; if (!(dcc[idx].u.bot->status & STAT_SHARE)) { tprintf(dcc[idx].sock,"error You didn't ask; you just started sending.\n"); tprintf(dcc[idx].sock,"error Ask before sending the userfile.\n"); zapfbot(idx); return; } if (dcc_total==MAXDCC) { putlog(LOG_MISC,"*","NO MORE DCC CONNECTIONS -- can't grab userfile"); tprintf(dcc[idx].sock,"error I can't open a DCC to you; I'm full.\n"); zapfbot(idx); return; } nsplit(ip,par); nsplit(port,par); i=dcc_total; dcc[i].addr=my_atoul(ip); dcc[i].port=atoi(port); dcc[i].sock=(-1); dcc[i].type=DCC_FORK; strcpy(dcc[i].nick,"*users"); strcpy(dcc[i].host,dcc[idx].nick); dcc[i].u.other=NULL; set_fork(i); get_xfer_ptr(&(dcc[i].u.fork->u.xfer)); strcpy(dcc[i].u.fork->u.xfer->filename,".share.users"); dcc[i].u.fork->u.xfer->dir[0]=0; /* this dir */ dcc[i].u.fork->u.xfer->length=atol(par); dcc[i].u.fork->u.xfer->sent=0; dcc[i].u.fork->u.xfer->sofar=0; dcc[i].u.fork->u.xfer->f=fopen(".share.users","w"); if (dcc[i].u.fork->u.xfer->f==NULL) { putlog(LOG_MISC,"*","CAN'T WRITE USERFILE DOWNLOAD FILE!"); nfree(dcc[i].u.fork->u.xfer); nfree(dcc[i].u.fork); zapfbot(idx); return; } dcc[idx].u.bot->status|=STAT_GETTING; dcc[i].u.fork->type=DCC_SEND; dcc_total++; /* don't buffer this */ dcc[i].sock=getsock(SOCK_BINARY); if (open_telnet_dcc(dcc[i].sock,ip,port) < 0) { putlog(LOG_MISC,"*","Asynchronous connection failed!"); tprintf(dcc[idx].sock,"error Can't connect to you!\n"); lostdcc(i); zapfbot(idx); } } void bot_resyncq PROTO2(int,idx,char *,par) { #ifndef ALLOW_RESYNC tprintf(dcc[idx].sock,"resync-no Not permitting resync.\n"); return; #else if (!share_users) tprintf(dcc[idx].sock,"resync-no Not sharing userfile.\n"); else if (!(get_attr_handle(dcc[idx].nick) & BOT_SHARE)) tprintf(dcc[idx].sock,"resync-no You are not +s for me.\n"); else if (can_resync(dcc[idx].nick)) { tprintf(dcc[idx].sock,"resync!\n"); dump_resync(dcc[idx].sock,dcc[idx].nick); dcc[idx].u.bot->status&=~STAT_OFFERED; dcc[idx].u.bot->status|=STAT_SHARE; putlog(LOG_BOTS,"*","Resync'd user file with %s",dcc[idx].nick); } else if (passive) { tprintf(dcc[idx].sock,"resync!\n"); dcc[idx].u.bot->status&=~STAT_OFFERED; dcc[idx].u.bot->status|=STAT_SHARE; putlog(LOG_BOTS,"*","Resyncing user file from %s",dcc[idx].nick); } else tprintf(dcc[idx].sock,"resync-no No resync buffer.\n"); #endif } void bot_resync PROTO2(int,idx,char *,par) { if (dcc[idx].u.bot->status&STAT_OFFERED) { if (can_resync(dcc[idx].nick)) { dump_resync(dcc[idx].sock,dcc[idx].nick); dcc[idx].u.bot->status&=~STAT_OFFERED; dcc[idx].u.bot->status|=STAT_SHARE; putlog(LOG_BOTS,"*","Resync'd user file with %s",dcc[idx].nick); } } } void bot_resync_no PROTO2(int,idx,char *,par) { putlog(LOG_BOTS,"*","Resync refused by %s: %s",dcc[idx].nick,par); flush_tbuf(dcc[idx].nick); tprintf(dcc[idx].sock,"userfile?\n"); } #define CHKSEND if (!(dcc[idx].u.bot->status&STAT_SENDING)) return #define CHKGET if (!(dcc[idx].u.bot->status&STAT_GETTING)) return #define CHKSHARE if (!(dcc[idx].u.bot->status&STAT_SHARE)) return void bot_chpass PROTO2(int,idx,char *,par) { char *hand=TBUF; CHKSHARE; shareout_but(idx,"chpass %s\n",par); noshare=1; nsplit(hand,par); change_pass_by_handle(hand,par); noshare=0; putlog(LOG_CMDS,"*","%s: newpass %s",dcc[idx].nick,hand); } void bot_chhand PROTO2(int,idx,char *,par) { char *hand=TBUF; int i; CHKSHARE; shareout_but(idx,"chhand %s\n",par); noshare=1; nsplit(hand,par); change_handle(hand,par); notes_change(-1,hand,par); noshare=0; putlog(LOG_CMDS,"*","%s: handle %s->%s",dcc[idx].nick,hand,par); for (i=0; ichannel>=0)) { chanout2(dcc[i].u.chat->channel,"Nick change: %s -> %s\n", dcc[i].nick,par); context; if (dcc[i].u.chat->channel < 100000) { tandout("part %s %s %d\n",botnetnick,dcc[i].nick,dcc[i].sock); tandout("join %s %s %d %c%d %s\n",botnetnick,par,dcc[i].u.chat->channel, geticon(i),dcc[i].sock,dcc[i].host); } } strcpy(dcc[i].nick,par); } } void bot_chattr PROTO2(int,idx,char *,par) { char *hand=TBUF,*atr=TBUF+50,*s=TBUF+512; int oatr,natr;struct chanset_t *cst; CHKSHARE; shareout_but(idx,"chattr %s\n",par); noshare=1; nsplit(hand,par); /* If user is a bot with +s, ignore command */ if (get_attr_handle(hand) & BOT_SHARE) { noshare=0; return; } nsplit(atr,par); if (par[0]) { if (defined_channel(par)) { cst=findchan(par); natr=atoi(atr); if (cst->stat&CHAN_SHARED) { set_chanattr_handle(hand,par,natr); noshare=0; chflags2str(get_chanattr_handle(hand,par),s); putlog(LOG_CMDS,"*","%s: chattr %s %s %s",dcc[idx].nick,hand,s,par); } else putlog(LOG_CMDS,"*","Rejected info for unshared channel %s from %s", par,dcc[idx].nick); } return; } /* don't let bot flags be altered */ oatr=(get_attr_handle(hand) & ~BOT_MASK); natr=atoi(atr); #ifdef PRIVATE_OWNER oatr|=(get_attr_handle(hand) & USER_OWNER); natr&=(~USER_OWNER); #endif set_attr_handle(hand,(natr & BOT_MASK)|oatr); noshare=0; flags2str(get_attr_handle(hand),s); putlog(LOG_CMDS,"*","%s: chattr %s %s",dcc[idx].nick,hand,s); } void bot_newuser PROTO2(int,idx,char *,par) { char *etc=TBUF,*etc2=TBUF+41,*etc3=TBUF+121; CHKSHARE; shareout_but(idx,"newuser %s\n",par); noshare=1; nsplit(etc,par); etc[40]=0; /* If user already exists, ignore command */ if(is_user(etc)) { noshare=0; return; } nsplit(etc2,par); etc2[80]=0; nsplit(etc3,par); userlist=adduser(userlist,etc,etc2,etc3,atoi(par)); noshare=0; putlog(LOG_CMDS,"*","%s: newuser %s",dcc[idx].nick,etc); } void bot_killuser PROTO2(int,idx,char *,par) { CHKSHARE; noshare=1; /* If user is a share bot, ignore command */ if(get_attr_handle(par) & BOT_SHARE) { noshare=0; return; } if (deluser(par)) { noshare=0; shareout_but(idx,"killuser %s\n",par); putlog(LOG_CMDS,"*","%s: killuser %s",dcc[idx].nick,par); } else noshare=0; } void bot_pls_upload PROTO2(int,idx,char *,par) { char *hand=TBUF; CHKSHARE; shareout_but(idx,"+upload %s\n",par); noshare=1; nsplit(hand,par); stats_add_upload(hand,atol(par)); noshare=0; /* no point logging this */ } void bot_pls_dnload PROTO2(int,idx,char *,par) { char *hand=TBUF; CHKSHARE; shareout_but(idx,"+dnload %s\n",par); noshare=1; nsplit(hand,par); stats_add_dnload(hand,atol(par)); noshare=0; /* no point logging this either */ } void bot_pls_host PROTO2(int,idx,char *,par) { char *hand=TBUF; CHKSHARE; shareout_but(idx,"+host %s\n",par); noshare=1; nsplit(hand,par); addhost_by_handle(hand,par); noshare=0; putlog(LOG_CMDS,"*","%s: +host %s %s",dcc[idx].nick,hand,par); } void bot_pls_bothost PROTO2(int,idx,char *,par) { char *hand=TBUF, *p=TBUF+512; CHKSHARE; shareout_but(idx,"+bothost %s\n",par); noshare=1; nsplit(hand,par); /* add bot to userlist if not there */ if (is_user(hand)) { if (!(get_attr_handle(hand) & USER_BOT)) { noshare=0; return; /* ignore */ } addhost_by_handle(hand,par); } else { makepass(p); userlist=adduser(userlist,hand,par,p,USER_BOT); } noshare=0; putlog(LOG_CMDS,"*","%s: +host %s %s",dcc[idx].nick,hand,par); } void bot_mns_host PROTO2(int,idx,char *,par) { char *hand=TBUF; CHKSHARE; shareout_but(idx,"-host %s\n",par); noshare=1; nsplit(hand,par); /* If user is a share bot, ignore command */ if (get_attr_handle(hand) & BOT_SHARE) { noshare=0; return; } delhost_by_handle(hand,par); noshare=0; putlog(LOG_CMDS,"*","%s: -host %s %s",dcc[idx].nick,hand,par); } void bot_chemail PROTO2(int,idx,char *,par) { char *hand=TBUF; CHKSHARE; shareout_but(idx,"chemail %s\n",par); noshare=1; nsplit(hand,par); set_handle_email(userlist,hand,par); noshare=0; putlog(LOG_CMDS,"*","%s: change email %s",dcc[idx].nick,hand); } void bot_chdccdir PROTO2(int,idx,char *,par) { char *hand=TBUF; CHKSHARE; shareout_but(idx,"chdccdir %s\n",par); noshare=1; nsplit(hand,par); set_handle_dccdir(userlist,hand,par); noshare=0; } void bot_chcomment PROTO2(int,idx,char *,par) { char *hand=TBUF; CHKSHARE; shareout_but(idx,"chcomment %s\n",par); noshare=1; nsplit(hand,par); set_handle_comment(userlist,hand,par); noshare=0; putlog(LOG_CMDS,"*","%s: change comment %s",dcc[idx].nick,hand); } void bot_chinfo PROTO2(int,idx,char *,par) { char *hand=TBUF; CHKSHARE; shareout_but(idx,"chinfo %s\n",par); noshare=1; nsplit(hand,par); set_handle_info(userlist,hand,par); noshare=0; putlog(LOG_CMDS,"*","%s: change info %s",dcc[idx].nick,hand); } void bot_chchinfo PROTO2(int,idx,char *,par) { char *hand=TBUF; char *chan=TBUF+512;struct chanset_t *cst; CHKSHARE; shareout_but(idx,"chchinfo %s\n",par); noshare=1; nsplit(hand,par); nsplit(chan,par); cst=findchan(chan); if (cst->stat&CHAN_SHARED) { set_handle_chaninfo(userlist,hand,chan,par); noshare=0; putlog(LOG_CMDS,"*","%s: change info %s %s",dcc[idx].nick,chan,hand); } else putlog(LOG_CMDS,"*","Info line change from %s denied. Channel %s not shared.", dcc[idx].nick,chan); } void bot_chaddr PROTO2(int,idx,char *,par) { char *hand=TBUF; CHKSHARE; shareout_but(idx,"chaddr %s\n",par); noshare=1; nsplit(hand,par); /* add bot to userlist if not there */ if (!is_user(hand)) userlist=adduser(userlist,hand,"none","-",USER_BOT); if (!(get_attr_handle(hand) & USER_BOT)) { noshare=0; return; /* ignore */ } set_handle_info(userlist,hand,par); noshare=0; putlog(LOG_CMDS,"*","%s: change address %s",dcc[idx].nick,hand); } void bot_clrxtra PROTO2(int,idx,char *,par) { CHKSHARE; shareout_but(idx,"clrxtra %s\n",par); noshare=1; set_handle_xtra(userlist,par,""); noshare=0; } void bot_addxtra PROTO2(int,idx,char *,par) { char *hand=TBUF; CHKSHARE; shareout_but(idx,"addxtra %s\n",par); noshare=1; nsplit(hand,par); add_handle_xtra(userlist,hand,par); noshare=0; } void bot_mns_ban PROTO2(int,idx,char *,par) { CHKSHARE; shareout_but(idx,"-ban %s\n",par); putlog(LOG_CMDS,"*","%s: cancel ban %s",dcc[idx].nick,par); noshare=1; delban(par); noshare=0; } void bot_mns_banchan PROTO2(int,idx,char *,par) { char *chname=TBUF; struct chanset_t *chan; CHKSHARE; shareout_but(idx,"-banchan %s\n",par); nsplit(chname,par); chan=findchan(chname); if (chan==NULL) return; putlog(LOG_CMDS,"*","%s: cancel ban %s on %s",dcc[idx].nick,par,chname); noshare=1; u_delban(chan->bans,par); noshare=0; } void bot_mns_ignore PROTO2(int,idx,char *,par) { CHKSHARE; shareout_but(idx,"-ignore %s\n",par); putlog(LOG_CMDS,"*","%s: cancel ignore %s",dcc[idx].nick,par); noshare=1; delignore(par); noshare=0; } void bot_pls_ban PROTO2(int,idx,char *,par) { time_t now=time(NULL),expire_time; char *ban=TBUF,*tm=TBUF+512,*from=TBUF+532; CHKSHARE; shareout_but(idx,"+ban %s\n",par); noshare=1; nsplit(ban,par); nsplit(tm,par); nsplit(from,par); if (from[strlen(from)-1]==':') from[strlen(from)-1]=0; putlog(LOG_CMDS,"*","%s: ban %s (%s: %s)",dcc[idx].nick,ban,from,par); /* new format? */ if (tm[0]=='+') { /* time left */ strcpy(tm,&tm[1]); expire_time=(time_t)atol(tm); if (expire_time!=0L) expire_time+=now; } else { expire_time=(time_t)atol(tm); if (expire_time!=0L) expire_time=(now-expire_time); } addban(ban,from,par,expire_time); noshare=0; } void bot_pls_banchan PROTO2(int,idx,char *,par) { time_t now=time(NULL),expire_time; struct chanset_t *chan; char *ban=TBUF,*tm=TBUF+512,*chname=TBUF+600,*from=TBUF+700; CHKSHARE; shareout_but(idx,"+banchan %s\n",par); nsplit(ban,par); nsplit(tm,par); nsplit(chname,par); nsplit(from,par); if (from[strlen(from)-1]==':') from[strlen(from)-1]=0; chan=findchan(chname); if (chan==NULL) return; putlog(LOG_CMDS,"*","%s: ban %s on %s (%s:%s)",dcc[idx].nick,ban,chname, from,par); noshare=1; /* new format? */ if (tm[0]=='+') { /* time left */ strcpy(tm,&tm[1]); expire_time=(time_t)atol(tm); if (expire_time!=0L) expire_time+=now; } else { expire_time=(time_t)atol(tm); if (expire_time!=0L) expire_time=(now-expire_time)+(60*ban_time); } u_addban(chan->bans,ban,from,par,expire_time); noshare=0; } /* +ignore + */ void bot_pls_ignore PROTO2(int,idx,char *,par) { time_t now=time(NULL),expire_time; char *ign=TBUF,*from=TBUF+256,*ts=TBUF+512; CHKSHARE; shareout_but(idx,"+ignore %s\n",par); noshare=1; nsplit(ign,par); if (par[0]=='+') { /* new-style */ nsplit(ts,par); strcpy(ts,&ts[1]); if (atoi(ts)==0) expire_time=0L; else expire_time=now+atoi(ts); nsplit(from,par); from[10]=0; par[65]=0; } else { if (atoi(par)==0) expire_time=0L; else expire_time=now+(60*ignore_time)-atoi(par); strcpy(from,dcc[idx].nick); strcpy(par,"-"); } putlog(LOG_CMDS,"*","%s: ignore %s (%s: %s)",dcc[idx].nick,ign,from,par); addignore(ign,from,par,expire_time); noshare=0; } void bot_nlinked PROTO2(int,idx,char *,par) { char *newbot=TBUF,*next=TBUF+512,*p; int reject=0,bogus=0,atr,i; nsplit(newbot,par); nsplit(next,par); if (strlen(newbot)>9) newbot[9]=0; if (strlen(next)>9) next[9]=0; if (!next[0]) { putlog(LOG_BOTS,"*","Invalid eggnet protocol from %s (zapfing)", dcc[idx].nick); chatout("*** Disconnected %s (invalid bot)\n",dcc[idx].nick); tandout_but(idx,"chat %s Disconnected %s (invalid bot)\n",botnetnick, dcc[idx].nick); tprintf(dcc[idx].sock,"error invalid eggnet protocol for 'nlinked'\n"); reject=1; } else if ((in_chain(newbot)) || (strcasecmp(newbot,botnetnick)==0)) { /* loop! */ putlog(LOG_BOTS,"*","Detected loop: disconnecting %s (mutual: %s)", dcc[idx].nick,newbot); chatout("*** Loop (%s): disconnected %s\n",newbot,dcc[idx].nick); tandout_but(idx,"chat %s Loop (%s): disconnected %s\n",botnetnick,newbot, dcc[idx].nick); tprintf(dcc[idx].sock,"error Loop (%s)\n",newbot); reject=1; } if (!reject) { for (p=newbot; *p; p++) if ((*p<32) || (*p==127)) bogus=1; i=nextbot(next); if (i!=idx) bogus=1; } if (bogus) { putlog(LOG_BOTS,"*","Bogus link notice from %s! (%s -> %s)",dcc[idx].nick, next,newbot); chatout("*** Bogus link notice: disconnecting %s\n",dcc[idx].nick); tandout_but(idx,"chat %s Bogus link notice: disconnecting %s\n", botnetnick,dcc[idx].nick); tprintf(dcc[idx].sock,"error Bogus link notice (%s -> %s)\n",next,newbot); reject=1; } atr=get_attr_handle(dcc[idx].nick); if (atr & BOT_LEAF) { putlog(LOG_BOTS,"*","Disconnecting leaf %s (linked to %s)",dcc[idx].nick, newbot); chatout("*** Illegal link by leaf %s (to %s): disconnecting\n", dcc[idx].nick,newbot); tandout_but(idx,"chat %s Illegal link by leaf %s (to %s): disconnecting\n", botnetnick,dcc[idx].nick,newbot); tprintf(dcc[idx].sock,"error You are supposed to be a leaf!\n"); reject=1; } if (reject) { tandout_but(idx,"unlinked %s\n",dcc[idx].nick); cancel_user_xfer(idx); rembot(dcc[idx].nick,dcc[idx].nick); unvia(idx,dcc[idx].nick); tprintf(dcc[idx].sock,"bye\n"); killsock(dcc[idx].sock); lostdcc(idx); return; } addbot(newbot,dcc[idx].nick,next); tandout_but(idx,"nlinked %s %s %s\n",newbot,next,par); check_tcl_link(newbot,next); if (get_attr_handle(newbot) & BOT_REJECT) { tprintf(dcc[idx].sock,"reject %s %s\n",botnetnick,newbot); putlog(LOG_BOTS,"*","Rejecting bot %s from %s",newbot,dcc[idx].nick); } } void bot_linked PROTO2(int,idx,char *,par) { putlog(LOG_BOTS,"*","Older bot detected (unsupported)"); chatout("*** Disconnected %s (outdated)\n",dcc[idx].nick); tandout_but(idx,"chat %s Disconnected %s (outdated)\n",botnetnick, dcc[idx].nick); tandout_but(idx,"unlinked %s\n",dcc[idx].nick); cancel_user_xfer(idx); rembot(dcc[idx].nick,dcc[idx].nick); unvia(idx,dcc[idx].nick); killsock(dcc[idx].sock); lostdcc(idx); } void bot_unlinked PROTO2(int,idx,char *,par) { int i; char bot[512]; nsplit(bot,par); i=nextbot(bot); if ((i>=0) && (i!=idx)) /* bot is NOT downstream along idx, so BOGUS! */ fake_alert(idx); else if (i>=0) { /* valid bot downstream of idx */ rembot(bot,dcc[idx].nick); unvia(idx,bot); tandout_but(idx,"unlinked %s\n",bot); } /* otherwise it's not even a valid bot, so just ignore! */ } void bot_trace PROTO2(int,idx,char *,par) { char *from=TBUF,*dest=TBUF+512; int i; /* trace */ nsplit(from,par); nsplit(dest,par); if (strcasecmp(dest,botnetnick)==0) { tprintf(dcc[idx].sock,"traced %s %s:%s\n",from,par,botnetnick); } else { i=nextbot(dest); if (i>=0) tprintf(dcc[i].sock,"trace %s %s %s:%s\n",from,dest,par,botnetnick); } } void bot_traced PROTO2(int,idx,char *,par) { char *to=TBUF,*ss=TBUF+512,*p; int i,sock; /* traced */ nsplit(to,par); p=strchr(to,'@'); if (p==NULL) p=to; else { *p=0; p++; } if (strcasecmp(p,botnetnick)==0) { splitc(ss,to,':'); if (ss[0]) sock=atoi(ss); else sock=(-1); for (i=0; i %s\n",par); } else { i=nextbot(p); if (i>=0) tprintf(dcc[i].sock,"traced %s@%s %s\n",to,p,par); } } /* reject */ void bot_reject PROTO2(int,idx,char *,par) { char *from=TBUF,*who=TBUF+81,*destbot=TBUF+41,*p; int i; nsplit(from,par); from[40]=0; p=strchr(from,'@'); if (p==NULL) p=from; else p++; i=nextbot(p); if (i!=idx) { fake_alert(idx); return; } if (strchr(par,'@')==NULL) { /* rejecting a bot */ i=nextbot(par); if (i<0) { tprintf(dcc[idx].sock,"priv %s %s Can't reject %s (doesn't exist)\n", botnetnick,from,par); } else if (strcasecmp(dcc[i].nick,par)==0) { /* i'm the connection to the rejected bot */ putlog(LOG_BOTS,"*","%s rejected %s",from,dcc[i].nick); tprintf(dcc[i].sock,"bye\n"); tandout_but(i,"unlinked %s\n",dcc[i].nick); tandout_but(i,"chat %s Disconnected %s (rejected by %s)\n",botnetnick, dcc[i].nick,from); chatout("*** Disconnected %s (rejected by %s)\n",dcc[i].nick,from); cancel_user_xfer(i); rembot(dcc[i].nick,dcc[i].nick); unvia(i,dcc[i].nick); killsock(dcc[i].sock); lostdcc(i); } else { if (i<0) tandout_but(idx,"reject %s %s\n",from,par); else tprintf(dcc[i].sock,"reject %s %s\n",from,par); } } else { /* rejecting user */ nsplit(destbot,par); destbot[40]=0; splitc(who,destbot,'@'); if (strcasecmp(destbot,botnetnick)==0) { /* kick someone here! */ int ok=0; #ifdef SHAREBOT_BOOTS p=strchr(from,'@'); if (p==NULL) p=from; else p++; if (!(get_attr_handle(p) & BOT_SHARE)) { add_note(from,botnetnick,"Remote boots are not allowed.",-1,0); return; } #endif #ifdef REMOTE_BOOTS for (i=0; (istatus|=STAT_LEAF; /* set capitalization the way they want it */ noshare=1; change_handle(dcc[idx].nick,par); noshare=0; strcpy(dcc[idx].nick,par); } void bot_handshake PROTO2(int,idx,char *,par) { change_pass_by_handle(dcc[idx].nick,par); if ((dcc[idx].u.bot->status&STAT_SHARE) && (!(dcc[idx].u.bot->status&STAT_GETTING)) && (!(dcc[idx].u.bot->status&STAT_SENDING))) { noshare=1; change_pass_by_handle(botnetnick,par); noshare=0; /* i have no idea what that is supposed to accomplish ^ robey 18dec96 */ } } void bot_trying PROTO2(int,idx,char *,par) { tandout_but(idx,"trying %s\n",par); /* currently ignore */ } void bot_end_trying PROTO2(int,idx,char *,par) { tandout_but(idx,"*trying %s\n",par); /* currently ignore */ } /* used to send a direct msg from Tcl on one bot to Tcl on another */ /* zapf */ void bot_zapf PROTO2(int,idx,char *,par) { char *from=TBUF,*to=TBUF+512; int i; nsplit(from,par); nsplit(to,par); i=nextbot(from); if (i!=idx) { fake_alert(idx); return; } if (strcasecmp(to,botnetnick)==0) { /* for me! */ char opcode[512]; nsplit(opcode,par); check_tcl_bot(from,opcode,par); return; } i=nextbot(to); if (i>=0) tprintf(dcc[i].sock,"zapf %s %s %s\n",from,to,par); } /* used to send a global msg from Tcl on one bot to every other bot */ /* zapf-broad */ void bot_zapfbroad PROTO2(int,idx,char *,par) { char *from=TBUF,*opcode=TBUF+512; int i; nsplit(from,par); nsplit(opcode,par); i=nextbot(from); if (i!=idx) { fake_alert(idx); return; } check_tcl_bot(from,opcode,par); tandout_but(idx,"zapf-broad %s %s %s\n",from,opcode,par); } /* show motd to someone */ void bot_motd PROTO2(int,idx,char *,par) { FILE *vv; char *s=TBUF,*who=TBUF+512,*p; int i; nsplit(who,par); if ((!par[0]) || (strcasecmp(par,botnetnick)==0)) { p=strchr(who,':'); if (p==NULL) p=who; else p++; putlog(LOG_CMDS,"*","#%s# motd",p); vv=fopen(motdfile,"r"); if (vv!=NULL) { tprintf(dcc[idx].sock,"priv %s %s --- MOTD file:\n",botnetnick,who); help_subst(NULL,NULL,0,1); while (!feof(vv)) { fgets(s,120,vv); if (!feof(vv)) { if (s[strlen(s)-1]=='\n') s[strlen(s)-1]=0; if (!s[0]) strcpy(s," "); help_subst(s,who,USER_BOT,1); if (s[0]) tprintf(dcc[idx].sock,"priv %s %s %s\n",botnetnick,who,s); } } fclose(vv); } else tprintf(dcc[idx].sock,"priv %s %s No MOTD file. :(\n",botnetnick, who); } else { /* pass it on */ i=nextbot(par); if (i>=0) tprintf(dcc[i].sock,"motd %s %s\n",who,par); } } /* assoc [link-flag] */ /* link-flag is Y if botlinking */ void bot_assoc PROTO2(int,idx,char *,par) { char *s=TBUF,*s1; int linking=0; nsplit(s,par); if (s[0]=='Y') { linking=1; nsplit(s,par); } if ((atoi(s)<1) || (atoi(s)>99999)) return; s1=get_assoc_name(atoi(s)); if (linking && ((s1==NULL) || (s1[0]==0) || (get_attr_handle(dcc[idx].nick) & BOT_HUB))) { add_assoc(par,atoi(s)); tandout_but(idx,"assoc %s %s\n",s,par); } else if (par[0]=='0') { s1=get_assoc_name(atoi(s)); if (s1!=NULL) { if (s1[0]==0) kill_assoc(atoi(s)); else add_assoc("",atoi(s)); } tandout_but(idx,"assoc %s 0\n",s); } else if (get_assoc(par)!=atoi(s)) { /* new one i didn't know about -- pass it on */ s1=get_assoc_name(atoi(s)); if (s1!=NULL) { if (s1[0]==0) { /* recently killed assoc */ tandout_but(idx,"assoc %s 0\n",s); kill_assoc(atoi(s)); return; } } add_assoc(par,atoi(s)); tandout_but(idx,"assoc %s %s\n",s,par); } } /* filereject */ void bot_filereject PROTO2(int,idx,char *,par) { char *path=TBUF,*tobot=TBUF+512,*to=TBUF+542,*p; int i; nsplit(path,par); nsplit(tobot,par); splitc(to,tobot,'@'); if (strcasecmp(tobot,botnetnick)==0) { /* for me! */ p=strchr(to,':'); if (p!=NULL) { *p=0; for (i=0; i=0) tprintf(dcc[i].sock,"filereject %s %s@%s %s\n",path,to,tobot,par); } } /* filreq */ void bot_filereq PROTO2(int,idx,char *,par) { char *from=TBUF,*tobot=TBUF+41; int i; nsplit(from,par); splitc(tobot,par,':'); if (strcasecmp(tobot,botnetnick)==0) { /* for me! */ /* process this */ #ifdef NO_FILE_SYSTEM tprintf(dcc[idx].sock,"priv %s %s I have no file system to grab files from.\n", botnetnick,from); #else remote_filereq(idx,from,par); #endif } else { /* pass it on */ i=nextbot(tobot); if (i>=0) tprintf(dcc[i].sock,"filereq %s %s:%s\n",from,tobot,par); } } /* filesend */ void bot_filesend PROTO2(int,idx,char *,par) { char *botpath=TBUF,*nick=TBUF+512,*tobot=TBUF+552,*sock=TBUF+692; int i; char *nfn; nsplit(botpath,par); nsplit(tobot,par); splitc(nick,tobot,'@'); splitc(sock,nick,':'); if (strcasecmp(tobot,botnetnick)==0) { /* for me! */ nfn=strrchr(botpath,'/'); if (nfn==NULL) { nfn=strrchr(botpath,':'); if (nfn==NULL) nfn=botpath; /* that's odd. */ else nfn++; } else nfn++; /* send it to 'nick' as if it's from me */ mprintf(serv,"PRIVMSG %s :\001DCC SEND %s %s\001\n",nick,nfn,par); } else { i=nextbot(tobot); if (i>=0) tprintf(dcc[i].sock,"filesend %s %s:%s@%s %s\n",botpath,sock,nick, tobot,par); } } void bot_error PROTO2(int,idx,char *,par) { putlog(LOG_MISC|LOG_BOTS,"*","%s: %s",dcc[idx].nick,par); } /* join */ void bot_join PROTO2(int,idx,char *,par) { char *bot=TBUF,*nick=TBUF+20,*x=TBUF+40,*y=TBUF+60,*from=TBUF+70; int i,sock; nsplit(bot,par); bot[9]=0; nsplit(nick,par); nick[9]=0; nsplit(x,par); x[10]=0; nsplit(y,par); /* only first char matters */ if (!y[0]) { y[0]='-'; sock=0; } else sock=atoi(&y[1]); /* 1.1 bots always send a sock#, even on a channel change */ /* so if sock# is 0, this is from an old bot and we must tread softly */ /* grab old sock# if there is one, otherwise make up one */ if (sock==0) sock=partysock(bot,nick); if (sock==0) sock=fakesock++; strncpy(from,par,40); from[40]=0; i=nextbot(bot); if (i!=idx) return; /* garbage sent by 1.0g bot */ addparty(bot,nick,atoi(x),y[0],sock,from); tandout_but(idx,"join %s %s %d %c%d %s\n",bot,nick,atoi(x),y[0],sock,from); check_tcl_chjn(bot,nick,atoi(x),y[0],sock,from); } /* part [etc..] */ void bot_part PROTO2(int,idx,char *,par) { char *bot=TBUF,*nick=TBUF+20,*etc=TBUF+40; int sock; nsplit(bot,par); bot[9]=0; nsplit(nick,par); nick[9]=0; nsplit(etc,par); sock=atoi(etc); if (sock==0) sock=partysock(bot,nick); check_tcl_chpt(bot,nick,sock); remparty(bot,sock); tandout_but(idx,"part %s %s %d %s\n",bot,nick,sock,par); } /* away */ void bot_away PROTO2(int,idx,char *,par) { char *bot=TBUF,*etc=TBUF+20; int sock; nsplit(bot,par); bot[9]=0; nsplit(etc,par); sock=atoi(etc); if (sock==0) sock=partysock(bot,etc); partystat(bot,sock,PLSTAT_AWAY,0); partyaway(bot,sock,par); tandout_but(idx,"away %s %d %s\n",bot,sock,par); } /* unaway */ void bot_unaway PROTO2(int,idx,char *,par) { char *bot=TBUF,*etc=TBUF+20; int sock; nsplit(bot,par); bot[9]=0; nsplit(etc,par); sock=atoi(etc); if (sock==0) sock=partysock(bot,etc); partystat(bot,sock,0,PLSTAT_AWAY); tandout_but(idx,"unaway %s %d %s\n",bot,sock,par); } /* (a courtesy info to help during connect bursts) */ /* idle <#secs> */ void bot_idle PROTO2(int,idx,char *,par) { char *bot=TBUF,*etc=TBUF+20; int sock; nsplit(bot,par); bot[9]=0; nsplit(etc,par); sock=atoi(etc); if (sock==0) sock=partysock(bot,etc); partysetidle(bot,sock,atoi(par)); tandout_but(idx,"idle %s %d %s\n",bot,sock,par); }