energymech/src/spy.c

545 lines
9.5 KiB
C
Raw Normal View History

2014-03-08 19:56:21 -05:00
/*
EnergyMech, IRC bot software
Parts Copyright (c) 1997-2004 proton
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#define SPY_C
#include "config.h"
#include "defines.h"
#include "structs.h"
#include "global.h"
#include "h.h"
#include "text.h"
#include "mcmd.h"
#ifdef DEBUG
LS const char SPY_DEFS[7][12] =
{
"SPY_FILE",
"SPY_CHANNEL",
"SPY_DCC",
"SPY_STATUS",
"SPY_MESSAGE",
"SPY_RAWIRC",
"SPY_BOTNET"
};
#endif /* DEBUG */
void send_spy(const char *src, const char *format, ...)
{
Chan *chan;
Mech *backup;
Spy *spy;
va_list msg;
const char *tempsrc;
char tempdata[MAXLEN];
int fd;
int printed = FALSE;
tempsrc = (src == SPYSTR_STATUS) ? time2medium(now) : src;
#ifdef DEBUG
debug("(send_spy) src %s format = '%s'\n",src,format);
#endif /* DEBUG */
for(spy=current->spylist;spy;spy=spy->next)
{
if ((*src == '#' || *src == '*') && spy->t_src == SPY_CHANNEL)
{
if ((*src != '*') && Strcasecmp(spy->src,src))
continue;
if ((chan = find_channel_ac(spy->src)) == NULL)
continue;
if (find_chanuser(chan,CurrentNick) == NULL)
continue;
tempsrc = spy->src;
}
else
/*
* by using string constants we can compare addresses
*/
if (spy->src != src)
continue;
if (!printed)
{
printed = TRUE;
va_start(msg,format);
vsprintf(tempdata,format,msg);
va_end(msg);
}
switch(spy->t_dest)
{
case SPY_DCC:
to_file(spy->dcc->sock,"[%s] %s\n",tempsrc,tempdata);
break;
case SPY_CHANNEL:
if (spy->destbot >= 0)
{
backup = current;
for(current=botlist;current;current=current->next)
{
if (current->guid == spy->destbot)
{
to_server("PRIVMSG %s :[%s] %s\n",spy->dest,tempsrc,tempdata);
break;
}
}
current = backup;
}
else
{
to_user(spy->dest,"[%s] %s",tempsrc,tempdata);
}
break;
case SPY_FILE:
if ((fd = open(spy->dest,O_WRONLY|O_CREAT|O_APPEND,NEWFILEMODE)) >= 0)
{
to_file(fd,"[%s] %s\n",logtime(now),tempdata);
close(fd);
}
}
}
}
void send_global(const char *src, const char *format, ...)
{
va_list msg;
Mech *backup;
char tempdata[MAXLEN];
int printed = FALSE;
backup = current;
for(current=botlist;current;current=current->next)
{
if (current->spy & SPYF_ANY)
{
if (!printed)
{
printed = TRUE;
va_start(msg,format);
vsprintf(tempdata,format,msg);
va_end(msg);
}
send_spy(src,FMT_PLAIN,tempdata);
}
}
current = backup;
}
void spy_typecount(Mech *bot)
{
Spy *spy;
bot->spy = 0;
for(spy=bot->spylist;spy;spy=spy->next)
{
bot->spy |= SPYF_ANY;
bot->spy |= (1 << spy->t_src);
}
}
struct
{
char *idstring;
int typenum;
2018-03-10 02:55:07 +01:00
} spy_source_list[] =
2014-03-08 19:56:21 -05:00
{
{ SPYSTR_STATUS, SPY_STATUS },
{ SPYSTR_MESSAGE, SPY_MESSAGE },
{ SPYSTR_RAWIRC, SPY_RAWIRC },
{ SPYSTR_BOTNET, SPY_BOTNET },
{ NULL, 0 },
};
int spy_source(char *from, int *t_src, char **src)
{
int i;
for(i=0;spy_source_list[i].idstring;i++)
{
if (!Strcasecmp(*src,spy_source_list[i].idstring))
{
*src = spy_source_list[i].idstring;
*t_src = spy_source_list[i].typenum;
return(200);
}
}
*t_src = SPY_CHANNEL;
if (!ischannel(*src))
return(-1);
return(get_useraccess(from,*src));
}
/*
*
* commands related to spy-pipes
*
*/
void do_spy(COMMAND_ARGS)
{
/*
* on_msg checks: CARGS
*/
Spy *spy;
Mech *backup,*destbot;
char *src,*dest;
int t_src,t_dest;
int sz;
int guid;
if (!*rest)
{
if (!current->spylist)
{
to_user(from,"No active spy channels");
return;
}
if (dcc_only_command(from))
return;
table_buffer("\037source\037\t\037target\037");
for(spy=current->spylist;spy;spy=spy->next)
{
switch(spy->t_src)
{
case SPY_MESSAGE:
src = "messages";
break;
default:
src = spy->src;
}
dest = (spy->t_dest == SPY_FILE) ? " (file)" : "";
table_buffer("%s\t%s%s",src,spy->dest,dest);
}
table_send(from,2);
return;
}
src = chop(&rest);
dest = chop(&rest);
if (!src)
{
spy_usage:
usage(from); /* usage for CurrentCmd->name */
return;
}
t_dest = SPY_DCC;
guid = -1;
destbot = NULL;
if (*src >= '0' && *src <= '9')
{
guid = 0;
while(*src && *src != ':')
{
guid = *src - '0';
src++;
}
if (*src != ':' && !ischannel(src+1))
goto spy_usage;
src++;
t_src = SPY_CHANNEL;
/*
* TODO: check access
*/
#ifdef DEBUG
debug("(do_spy) spy source guid = %i, channel = %s\n",guid,src);
#endif /* DEBUG */
/*
* is it a bot?
* TODO: check botnet bots also
*/
for(backup=botlist;backup;backup=backup->next)
{
if (backup->guid == guid)
{
destbot = backup;
goto guid_ok;
}
}
to_user(from,"Unknown bot guid: %i",guid);
return;
guid_ok:
;
}
else
{
sz = spy_source(from,&t_src,&src);
if (sz < 0)
goto spy_usage;
if (sz < cmdaccess)
return;
}
if (dest)
{
/*
* log to a file
*/
if (*dest == '>')
{
dest++;
if (!*dest)
{
dest = chop(&rest);
if (!dest || !*dest)
goto spy_usage;
}
/*
* Dont just open anything.
*/
if (!is_safepath(dest))
goto spy_usage;
t_dest = SPY_FILE;
goto spy_dest_ok;
}
if (!ischannel(dest))
goto spy_usage;
if (get_useraccess(from,dest) < cmdaccess)
{
to_user(from,"You don't have enough access on %s",dest);
return;
}
t_dest = SPY_CHANNEL;
}
spy_dest_ok:
#ifdef DEBUG
debug("(do_spy) src = `%s'; t_src = %i (%s); dest = `%s'; t_dest = %i (%s)\n",
src,t_src,SPY_DEFS[t_src-1],nullstr(dest),t_dest,SPY_DEFS[t_dest-1]);
if (guid >= 0)
debug("(do_spy) spying from remote bot guid %i (%s) channel %s\n",guid,(destbot) ? destbot->nick : "unknown",src);
#endif /* DEBUG */
if (t_dest == SPY_DCC)
{
if (!CurrentDCC)
{
to_user(from,"Spying is only allowed in DCC chat");
return;
}
dest = CurrentDCC->user->name;
}
for(spy=current->spylist;spy;spy=spy->next)
{
if ((spy->t_src == t_src) && (spy->t_dest == t_dest) &&
!Strcasecmp(spy->src,src) && !Strcasecmp(spy->dest,dest))
{
to_user(from,"Requested spy channel is already active");
return;
}
}
set_mallocdoer(do_spy);
sz = sizeof(Spy);
if (t_dest != SPY_DCC)
sz += strlen(dest);
if (t_src == SPY_CHANNEL)
sz += strlen(src);
spy = Calloc(sz);
if (t_dest != SPY_DCC)
{
spy->dest = spy->p;
spy->src = Strcat(spy->p,dest) + 1;
}
else
{
spy->dest = CurrentDCC->user->name;
spy->dcc = CurrentDCC;
spy->src = spy->p;
}
if (t_src == SPY_CHANNEL)
{
Strcpy(spy->src,src);
}
else
{
spy->src = src;
}
spy->t_src = t_src;
spy->t_dest = t_dest;
/*
* finally link the spy record into the chain
* TODO: botnet bots
*/
if (guid >= 0)
{
if (destbot)
{
spy->destbot = current->guid;
spy->next = destbot->spylist;
destbot->spylist = spy;
spy_typecount(destbot);
}
}
else
{
spy->destbot = -1;
spy->next = current->spylist;
current->spylist = spy;
spy_typecount(current);
}
switch(t_src)
{
case SPY_STATUS:
send_spy(SPYSTR_STATUS,"(%s) Added to mech core",nickcpy(NULL,from));
break;
case SPY_MESSAGE:
src = "messages";
default:
to_user(from,"Spy channel for %s has been activated",src);
}
}
void do_rspy(COMMAND_ARGS)
{
/*
* on_msg checks: CARGS
*/
Spy *spy,**pspy;
char *src,*dest,*tmp;
int t_src,t_dest;
int n;
src = chop(&rest);
dest = chop(&rest);
t_dest = SPY_DCC;
if (!src)
{
rspy_usage:
usage(from); /* usage for CurrentCmd->name */
return;
}
n = spy_source(from,&t_src,&src);
if (n < 0)
goto rspy_usage;
if (n < cmdaccess)
return;
if (dest)
{
if (*dest == '>')
{
dest++;
if (!*dest)
{
dest = chop(&rest);
if (!dest || !*dest)
goto rspy_usage;
}
/*
* Dont just open anything.
*/
if (!is_safepath(dest))
2018-03-10 02:55:07 +01:00
#ifdef NEWBIE
{
usage(from);
to_user(from,"File/path does not exist or is inaccessible");
return;
}
#else
2014-03-08 19:56:21 -05:00
goto rspy_usage;
2018-03-10 02:55:07 +01:00
#endif /* NEWBIE */
2014-03-08 19:56:21 -05:00
t_dest = SPY_FILE;
goto rspy_dest_ok;
}
if (ischannel(dest))
t_dest = SPY_CHANNEL;
}
else
dest = from;
rspy_dest_ok:
#ifdef DEBUG
debug("(do_rspy) src = `%s'; t_src = %i (%s); dest = `%s'; t_dest = %i (%s)\n",
src,t_src,SPY_DEFS[t_src-1],dest,t_dest,SPY_DEFS[t_dest-1]);
#endif /* DEBUG */
/*
* check if the spy channel exists
*/
for(spy=current->spylist;spy;spy=spy->next)
{
if ((spy->t_src == t_src) && (spy->t_dest == t_dest) && (!Strcasecmp(spy->src,src)))
{
if ((t_dest == SPY_DCC) && (!nickcmp(spy->dest,dest)))
break;
else
if (!Strcasecmp(spy->dest,dest))
break;
}
}
if (!spy)
{
to_user(from,"No matching spy channel could be found");
return;
}
switch(t_src)
{
case SPY_STATUS:
tmp = (t_dest == SPY_DCC) ? nickcpy(NULL,spy->dest) : spy->dest;
send_spy(SPYSTR_STATUS,"(%s) Removed from mech core",tmp);
break;
case SPY_MESSAGE:
src = "messages";
default:
to_user(from,"Spy channel for %s has been removed",src);
break;
}
pspy = &current->spylist;
while(*pspy)
{
if (*pspy == spy)
{
*pspy = spy->next;
Free((char**)&spy);
return;
}
pspy = &(*pspy)->next;
}
spy_typecount(current);
}