diff --git a/.gitignore b/.gitignore index cc9f56b..0a6f77a 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,8 @@ src/energymech src/gencmd src/mcmd.h src/usercombo.h +src/aliastest +src/safepathtest *~ *.bak diff --git a/Makefile b/Makefile index 251cfd8..dc32a4f 100644 --- a/Makefile +++ b/Makefile @@ -92,6 +92,14 @@ mega: FORCE mega-install: FORCE $(MAKE) -C src mega-install + +# +# code validation tests +# + +test: FORCE + $(MAKE) -C src test + # # packing things up for distribution # diff --git a/README b/README index 5a382cc..eb9bd44 100644 --- a/README +++ b/README @@ -135,4 +135,4 @@ IT COMES TO CONFIGURING AND USING IT. ---*--- -joonicks, March 10th, 2018. +proton, March 13th, 2018. diff --git a/VERSIONS b/VERSIONS index 7b5b88f..b4265ca 100644 --- a/VERSIONS +++ b/VERSIONS @@ -1,5 +1,10 @@ 3.0.99p4 -- WORK IN PROGRESS (~March, 2018) + * Added: URL capturing with command to display recent URLs seen + by the bot. Also spy source "URL" for spy channels. + * Fixed: Rewrite of is_safepath() to conform with standard C + * Fixed: Potential crash bug in send_uptime() + * Fixed: Potential crash bug in debug() * Added: New host information commands: HOSTINFO, MEMINFO, CPUINFO. * Added: New configuration option: hostinfo * Fixed: Custom ld script fintuning the core order. diff --git a/configure b/configure index aa6a09d..88e6add 100755 --- a/configure +++ b/configure @@ -79,6 +79,7 @@ do toybox ) ft_toybox=$yesno ;; trivia ) ft_trivia=$yesno ;; uptime ) ft_uptime=$yesno ;; + urlcapture ) ft_urlcapture=$yesno ;; web ) ft_web=$yesno ;; wingate ) ft_wingate=$yesno ;; esac @@ -109,7 +110,7 @@ do case "$feature" in debug | botnet | telnet | alias | seen | session | dyncmd | newbie | wingate | md5 | sha \ | ctcp | dccfile | uptime | redirect | greet | perl | profiling | tcl | dynamode | web | hostinfo \ - | note | notify | trivia | toybox | bounce | stats | rawdns | ircd_ext | idwrap | chanban | python ) + | note | notify | trivia | toybox | bounce | stats | rawdns | ircd_ext | idwrap | chanban | python | urlcapture ) case _"$optarg"_ in _yes_ | _no_ | __ ) ;; @@ -193,6 +194,8 @@ do trivia_no ) ft_trivia=no ;; uptime_yes | uptime_ ) ft_uptime=yes ;; uptime_no ) ft_uptime=no ;; + urlcapture_yes | urlcapture_ ) ft_urlcapture=yes ;; + urlcapture_no ) ft_urlcapture=no ;; web_yes | web_ ) ft_web=yes ;; web_no ) ft_web=no ;; wingate_yes | wingate_ ) ft_wingate=yes ;; @@ -234,6 +237,7 @@ do toybox ) ft_toybox=no ;; trivia ) ft_trivia=no ;; uptime ) ft_uptime=no ;; + urlcapture ) ft_urlcapture=no ;; web ) ft_web=no ;; wingate ) ft_wingate=no ;; esac @@ -280,6 +284,7 @@ do ft_toybox=yes ft_trivia=yes ft_uptime=yes + ft_urlcapture=yes ft_web=yes ft_wingate=yes ;; @@ -302,13 +307,15 @@ Features and packages: --with-debug Debug support --with-dyncmd Dynamic command levels support --with-hostinfo Support for code that reveals/displays/shares information about the host - that the bot is running on. + that the bot is running on --with-newbie Newbie support --with-profiling Profiling (gcc+gprof) --with-seen SEEN support --with-session Session support --with-tcl Tcl support --with-telnet Telnet support + --with-uptime Include code that sends uptime reports to the IRC bot uptime contest server + --with-urlcapture URL capture support --with-wingate Wingate support __EOT__ exit 0 @@ -1186,6 +1193,13 @@ test "$ft_uptime" && echo "$ft_uptime" && ans=$ft_uptime test -z "$ft_uptime" && read ans test -z "$ans" -o "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes && def_uptime='#define UPTIME' +def_urlcapture='#undef URLCAPTURE' +unset ans +echo $ac_n "URL capture support? ....................... [Y/n] "$ac_c +test "$ft_urlcapture" && echo "$ft_urlcapture" && ans=$ft_urlcapture +test -z "$ft_urlcapture" && read ans +test -z "$ans" -o "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes && def_urlcapture='#define URLCAPTURE' + def_wingate='#undef WINGATE' unset ans echo $ac_n "WinGate support? ........................... [Y/n] "$ac_c @@ -1265,6 +1279,7 @@ s|@DEF_REDIRECT@|$def_redirect|; s|@DEF_TOYBOX@|$def_toybox|; s|@DEF_TRIVIA@|$def_trivia|; s|@DEF_UPTIME@|$def_uptime|; +s|@DEF_URLCAPTURE@|$def_urlcapture|; s|@DEF_WEB@|$def_web|; s|@DEF_WINGATE@|$def_wingate|; diff --git a/src/Makefile.in b/src/Makefile.in index 1ef524d..3f45bb6 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -42,18 +42,20 @@ CHMOD = chmod INCS = config.h mcmd.h defines.h global.h h.h structs.h text.h +TESTFILES = aliastest safepathtest + OFILES = alias.o auth.o bounce.o chanban.o channel.o core.o \ ctcp.o debug.o dns.o dynamode.o function.o greet.o help.o hostinfo.o irc.o \ kicksay.o main.o net.o net_chan.o note.o notify.o ons.o parse.o \ perl.o prot.o python.o redirect.o reset.o seen.o shit.o socket.o \ - spy.o stats.o tcl.o telnet.o toybox.o trivia.o uptime.o \ + spy.o stats.o tcl.o telnet.o toybox.o trivia.o uptime.o urlcap.o \ user.o vars.o web.o @MD5_O@ @SHA_O@ SRCFILES = alias.c auth.c bounce.c chanban.c channel.c core.c \ ctcp.c debug.c dns.c dynamode.c function.c greet.c help.c hostinfo.c irc.c \ kicksay.c main.c net.c net_chan.c note.c notify.c ons.c parse.c \ perl.c prot.c python.c redirect.c reset.c seen.c shit.c socket.c \ - spy.c stats.c tcl.c telnet.c toybox.c trivia.c uptime.c \ + spy.c stats.c tcl.c telnet.c toybox.c trivia.c uptime.c urlcap.c \ user.c vars.c web.c all: $(INSTALLNAME) @@ -72,7 +74,7 @@ install: $(INSTALLNAME) $(MV) $(INSTALLNAME) $(INSTALLDIR) clean: FORCE - $(RM) $(INSTALLNAME) gencmd mcmd.h core aliastest $(OFILES) + $(RM) $(INSTALLNAME) gencmd mcmd.h core $(TESTFILES) $(OFILES) $(INSTALLNAME): $(OFILES) $(CROSS_COMPILE)$(CC) $(LFLAGS) -o $(INSTALLNAME) $(OFILES) $(LPROF) $(LIBS) $(LDSCRIPT) @@ -109,8 +111,15 @@ mega-static: $(SRCFILES) $(INCS) usage.h # testing stuff # +test: $(TESTFILES) + ./aliastest + ./safepathtest + aliastest: alias.c - $(CROSS_COMPILE)$(CC) $(CFLAGS) -o aliastest $< $(LPROF) $(LIBS) $(LDSCRIPT) -DALIASTEST + $(CROSS_COMPILE)$(CC) $(CFLAGS) -o aliastest $< $(LPROF) $(LIBS) $(LDSCRIPT) -DTEST + +safepathtest: function.c + $(CROSS_COMPILE)$(CC) $(CFLAGS) -o safepathtest $< $(LPROF) $(LIBS) $(LDSCRIPT) -DTEST # # @@ -230,6 +239,9 @@ trivia.o: trivia.c $(INCS) uptime.o: uptime.c $(INCS) $(CROSS_COMPILE)$(CC) $(CFLAGS) -c $< $(CPROF) +urlcap.o: urlcap.c $(INCS) + $(CROSS_COMPILE)$(CC) $(CFLAGS) -c $< $(CPROF) + user.o: user.c $(INCS) $(CROSS_COMPILE)$(CC) $(CFLAGS) -c $< $(CPROF) diff --git a/src/alias.c b/src/alias.c index 9b55b44..9cc78bb 100644 --- a/src/alias.c +++ b/src/alias.c @@ -23,29 +23,17 @@ #ifdef ALIAS #include "defines.h" #include "structs.h" -#ifdef ALIASTEST +#ifdef TEST #define MAIN_C #endif #include "global.h" - -#ifndef ALIASTEST #include "h.h" #include "text.h" #include "mcmd.h" -#else /* ALIASTEST */ -void afmt(char *, const char *, const char *); +#ifdef TEST -void debug(char *format, ...) -{ - va_list msg; - - va_start(msg,format); - vsprintf(debugbuf,format,msg); - va_end(msg); - - write(1,debugbuf,strlen(debugbuf)); -} +#include "debug.c" char result[MSGLEN]; char *input = "alias one two three four five six seven eight nine ten"; @@ -60,6 +48,8 @@ void testcase(const char *test, const char *expect) int main(int argc, char **argv) { char *format = argv[1]; + + dodebug = 1; strcpy(CurrentNick,"noob"); if (format == NULL) { @@ -89,7 +79,7 @@ int main(int argc, char **argv) exit(0); } -#endif /* ALIASTEST */ +#endif /* TEST */ /* * copy_to = buffer to put resulting new command into @@ -160,7 +150,9 @@ void afmt(char *copy_to, const char *src, const char *input) } } #ifdef DEBUG +#ifndef TEST debug("(afmt) args #%i-#%i, characters %i-%i\n",startnum,endnum,argstart-input,argend-input); +#endif /* ifndef TEST */ #endif /* DEBUG */ while(*argstart && argstart < argend && dest <= BUFTAIL) *(dest++) = *(argstart++); @@ -172,11 +164,13 @@ void afmt(char *copy_to, const char *src, const char *input) } *dest = 0; #ifdef DEBUG +#ifndef TEST debug("(afmt) start %i end %i spc %i\n",startnum,endnum,spc); +#endif /* ifndef TEST */ #endif /* DEBUG */ } -#ifndef ALIASTEST +#ifndef TEST /* * @@ -290,6 +284,6 @@ void do_unalias(COMMAND_ARGS) to_user(from,"Couldnt find matching alias"); } -#endif /* not ALIASTEST */ +#endif /* not TEST */ #endif /* ALIAS */ diff --git a/src/channel.c b/src/channel.c index f7b8b90..77e95d2 100644 --- a/src/channel.c +++ b/src/channel.c @@ -1,7 +1,7 @@ /* EnergyMech, IRC bot software - Parts Copyright (c) 1997-2009 proton + Parts Copyright (c) 1997-2018 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 @@ -59,7 +59,7 @@ void check_idlekick(void) } __attr (CORE_SEG, regparm(2)) -Chan *find_channel(char *name, int anychannel) +Chan *find_channel(const char *name, int anychannel) { Chan *chan; uchar ni; @@ -79,13 +79,13 @@ Chan *find_channel(char *name, int anychannel) } __attr(CORE_SEG, __regparm (1)) -Chan *find_channel_ac(char *name) +Chan *find_channel_ac(const char *name) { return(find_channel(name,CHAN_ACTIVE)); } __attr(CORE_SEG, __regparm (1)) -Chan *find_channel_ny(char *name) +Chan *find_channel_ny(const char *name) { return(find_channel(name,CHAN_ANY)); } diff --git a/src/config.h.in b/src/config.h.in index 1a03820..9772dc4 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -192,6 +192,11 @@ */ @DEF_HOSTINFO@ +/* + * URLCAPTURE: capture url's mentioned + */ +@DEF_URLCAPTURE@ + /* * FASTNICK: faster nick regain if the nick is seen when released * Enables code that is potentially dangerous if an attacker aquires diff --git a/src/ctcp.c b/src/ctcp.c index 55586fc..10d0851 100644 --- a/src/ctcp.c +++ b/src/ctcp.c @@ -551,7 +551,7 @@ void ctcp_dcc(char *from, char *to, char *rest) debug("(ctcp_dcc) rest: `%s'\n",nullstr(rest)); #endif /* DEBUG */ filename = chop(&rest); - if (!is_safepath(filename)) + if (is_safepath(filename,FILE_MUST_EXIST) != FILE_IS_SAFE) { #ifdef DEBUG debug("(ctcp_dcc) filename `%s' is not safe\n",filename); diff --git a/src/debug.c b/src/debug.c index bdf6a24..43966d2 100644 --- a/src/debug.c +++ b/src/debug.c @@ -29,6 +29,8 @@ #include "h.h" #include "settings.h" +#ifndef TEST + #define boolstr(x) (x) ? "TRUE" : "FALSE" LS const char tabs[20] = "\t\t\t\t\t\t\t\t\t\t"; @@ -184,6 +186,9 @@ LS struct { init_uptime, "init_uptime" }, { send_uptime, "send_uptime" }, #endif /* UPTIME */ +#ifdef URLCAPTURE +{ urlcapture, "urlcapture" }, +#endif /* URLCAPTURE */ { 0, "(unknown)" }, { NULL, }}; @@ -1300,7 +1305,7 @@ int wrap_debug(void) close(fd); debug_fd = backup_fd; - dodebug = backup_dodebug; + dodebug = backup_dodebug; debug("(wrap_debug) all done.\n"); return(1); @@ -1314,6 +1319,8 @@ void do_debug(COMMAND_ARGS) to_user(from,"Unable to write debug information to file"); } +#endif /* ifndef TEST */ + void debug(char *format, ...) { va_list msg; @@ -1339,7 +1346,7 @@ void debug(char *format, ...) } va_start(msg,format); - vsprintf(debugbuf,format,msg); + vsnprintf(debugbuf,sizeof(debugbuf),format,msg); va_end(msg); if ((write(debug_fd,debugbuf,strlen(debugbuf))) < 0) diff --git a/src/defines.h b/src/defines.h index 3ccf59e..379d436 100644 --- a/src/defines.h +++ b/src/defines.h @@ -1,7 +1,7 @@ /* EnergyMech, IRC bot software - Parts Copyright (c) 1997-2009 proton + Parts Copyright (c) 1997-2018 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 @@ -161,6 +161,14 @@ #define IsChar(x) ((VarName[x].type & CHR_VAR) == CHR_VAR) #define IsProc(x) (VarName[x].type & PROC_VAR) +/* + * is_safepath + */ +#define FILE_IS_SAFE 1 +#define FILE_MUST_EXIST 1 +#define FILE_MAY_EXIST 2 +#define FILE_MUST_NOTEXIST 3 + /* * see settings.h for the actual setting struct */ @@ -264,6 +272,9 @@ enum { STR_UPNICK, INT_UPPORT, #endif /* UPTIME */ +#ifdef URLCAPTURE + INT_URLHISTMAX, +#endif /* URLCAPTURE */ STR_USERFILE, STR_VIRTUAL, #ifdef WEB @@ -381,6 +392,9 @@ enum { #define SPY_MESSAGE 5 #define SPY_RAWIRC 6 #define SPY_BOTNET 7 +#ifdef URLCAPTURE +#define SPY_URL 8 +#endif /* URLCAPTURE */ #define SPYF_ANY 1 #define SPYF_CHANNEL (1 << SPY_CHANNEL) @@ -388,6 +402,7 @@ enum { #define SPYF_MESSAGE (1 << SPY_MESSAGE) #define SPYF_RAWIRC (1 << SPY_RAWIRC) #define SPYF_BOTNET (1 << SPY_BOTNET) +#define SPYF_URL (1 << SPY_URL) /* * notify defines diff --git a/src/function.c b/src/function.c index e8e1a50..675a4d3 100644 --- a/src/function.c +++ b/src/function.c @@ -1,7 +1,7 @@ /* EnergyMech, IRC bot software - Parts Copyright (c) 1997-2009 proton + Parts Copyright (c) 1997-2018 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 @@ -23,25 +23,19 @@ #include "defines.h" #include "structs.h" +#ifdef TEST +#define MAIN_C +#endif #include "global.h" #include "h.h" #include "text.h" +#ifndef TEST + LS char timebuf[24]; /* max format lentgh == 20+1, round up to nearest longword -> 24 */ LS char idlestr[36]; /* max format lentgh == 24+1, round up to nearest longword -> 28 */ - -LS const char monlist[12][4] = -{ - "Jan", "Feb", "Mar", "Apr", - "May", "Jun", "Jul", "Aug", - "Sep", "Oct", "Nov", "Dec" -}; - -LS const char daylist[7][4] = -{ - "Sun", "Mon", "Tue", "Wed", - "Thu", "Fri", "Sat" -}; +LS const char monlist[12][4] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; +LS const char daylist[7][4] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; /* * memory allocation routines @@ -493,7 +487,7 @@ char *cluster(char *hostname) } else { - /* + /* * its not a numeric mask */ p = mask; @@ -841,7 +835,8 @@ char *Strchr(const char *t, int c) return((*t == ch) ? (char*)t : NULL); } -char *Strdup(char *src) +__attr(CORE_SEG,__regparm(1)) +char *Strdup(const char *src) { char *dest; @@ -1064,6 +1059,8 @@ void table_send(const char *from, const int space) e_table = NULL; } +#ifdef OLDCODE + int is_safepath(const char *path) { struct stat st; @@ -1097,3 +1094,125 @@ int is_safepath(const char *path) } return(path_token_check() == 1 ? TRUE : FALSE); } + +#endif + +#endif /* ifndef TEST at the beginning of file */ + +#define FILE_MUST_EXIST 1 +#define FILE_MAY_EXIST 2 +#define FILE_MUST_NOTEXIST 3 + +__attr(CORE_SEG,__regparm(2)) +int is_safepath(const char *path, int filemustexist) +{ + struct stat st; + ino_t ino; + char tmp[PATH_MAX]; + const char *src; + char *dst; + int r,mo,dir_r,orr,oerrno; + +#ifdef TEST + memset(&st,0,sizeof(st)); +#endif + if (*(src = path) == '/') // dont allow starting at root, only allow relative paths + return(-1);//(FALSE); + + if (strlen(path) >= PATH_MAX) + return(-6); + + orr = lstat(path,&st); + oerrno = errno; + + if (filemustexist == FILE_MUST_EXIST && orr == -1 && errno == ENOENT) + return(-2); + if (filemustexist == FILE_MUST_NOTEXIST && orr == 0) + return(-3); + + mo = st.st_mode; // save mode for later + dir_r = -1; + + for(dst=tmp;*src;) + { + if (*src == '/') + { + *dst = 0; + if ((dir_r = lstat(tmp,&st)) == -1 && errno == ENOENT) + return(-7); + if (!(S_ISREG(st.st_mode) || S_ISDIR(st.st_mode))) // disallow all except regular files and directories + return(-4); + if (st.st_ino == parent_inode) // disallow traversing below bots homedir + return(-5); + } + if (dst == tmp + PATH_MAX-1) + return(-6); + *dst++ = *src++; + } + if (filemustexist != FILE_MUST_EXIST && orr == -1 && oerrno == ENOENT) + return(TRUE); + return (S_ISREG(mo)) ? TRUE : FALSE; +} + +#ifdef TEST + +#include "debug.c" + +#define P0 "verylongexcessivelengthfilenamegibberish" +#define P1 P0 "/" P0 "/" P0 "/" P0 "/" P0 "/" P0 "/" P0 "/" P0 "/" P0 "/" P0 "/" +#define P2 P1 P1 P1 P1 P1 P1 P1 P1 P1 P1 P1 P1 P1 P1 P1 P1 P1 P1 P1 P1 P1 P1 P0 + +char *tostr[] = { "ZERO", "FILE_MUST_EXIST", "FILE_MAY_EXIST", "FILE_MUST_NOTEXIST" }; + +void testcase(const char *str, int expected, int filemustexist) +{ + int r; + + r = is_safepath(str,filemustexist); + if (r == expected) + { + debug("testcase SUCCESS: testpath %s %s -> result %i\n", + (strlen(str)>50) ? "(very long string)" : str,tostr[filemustexist],r); + } + else + { + debug("testcase FAIL: testpath %s(%i) %s -> result %i, expected %i\n", + (strlen(str)>50) ? "(very long string)" : str, + strlen(str),tostr[filemustexist],r,expected);//(r) ? "TRUE" : "FALSE",(expected) ? "TRUE" : "FALSE"); + } +} + +int main(int argc, char **argv) +{ + struct stat st; + int r; + + dodebug = 1; + stat("../..",&st); + parent_inode = st.st_ino; // used for is_safepath() + + debug("PATH_MAX = %i\n",PATH_MAX); + if (argv[1] == NULL) + { + testcase("/etc/passwd",-1,FILE_MAY_EXIST); + testcase("../../../../../../../../../../../etc/passwd",-5,FILE_MAY_EXIST); + testcase("../anyparentfile",1,FILE_MAY_EXIST); + testcase("../../anyparentparentfile",-5,FILE_MAY_EXIST); + testcase("function.c",TRUE,FILE_MUST_EXIST); + testcase("./function.c",TRUE,FILE_MUST_EXIST); + testcase("function.c",-3,FILE_MUST_NOTEXIST); + testcase("./function.c",-3,FILE_MUST_NOTEXIST); + testcase("nosuchfile",1,FILE_MAY_EXIST); + testcase("nosuchfile",1,FILE_MUST_NOTEXIST); + testcase("./nosuchfile",1,FILE_MUST_NOTEXIST); + testcase("../../nosuchfile",-5,FILE_MUST_NOTEXIST); + testcase(P2,-6,FILE_MAY_EXIST); + exit(0); + } + + r = is_safepath(argv[1],FILE_MAY_EXIST); + debug("testpath %s -> result %s\n",argv[1],(r) ? "TRUE" : "FALSE"); +} + +#endif /* TEST */ + diff --git a/src/gencmd.c b/src/gencmd.c index a4606d2..4f4dd71 100644 --- a/src/gencmd.c +++ b/src/gencmd.c @@ -91,6 +91,9 @@ struct #ifdef SEEN { 0, "SEEN", "do_seen", 20 | CCPW | CBANG }, #endif /* SEEN */ +#ifdef URLCAPTURE + { 0, "URLHIST", "do_urlhist", 20 | CCPW | REDIR | LBUF }, +#endif /* ifdef URLCAPTURE */ /* * Level 40 @@ -276,7 +279,7 @@ int main(int argc, char **argv) ct = 0; printf("/""* This file is automatically generated from gencmd.c *""/\n"); - printf("#ifndef MCMD_H\n#define MCMD_H 1\n\n"); + printf("#ifndef TEST\n#ifndef MCMD_H\n#define MCMD_H 1\n\n"); while(pass) { @@ -401,6 +404,7 @@ int main(int argc, char **argv) printf("extern OnMsg_access acmd[];\n\n"); printf("#endif /""* MAIN_C *""/\n\n"); printf("#endif /""* MCMD_H *""/\n\n"); + printf("#endif /""* TEST *""/\n\n"); unlink("usercombo.h"); of = fopen("usercombo.h","w"); diff --git a/src/global.h b/src/global.h index f6104fb..55ff390 100644 --- a/src/global.h +++ b/src/global.h @@ -41,7 +41,7 @@ #define MECHUSERLOGIN "v3.energymech.net" BEG const char VERSION[] MDEF("3.0.99p4"); -BEG const char SRCDATE[] MDEF("March 9th, 2018"); +BEG const char SRCDATE[] MDEF("March 13th, 2018"); #ifdef __CYGWIN__ BEG const char BOTCLASS[] MDEF("WinMech"); #else /* ! CYGWIN */ @@ -63,10 +63,15 @@ BEG const char __SPYSTR_RAWIRC[] MDEF("rawirc"); BEG const char __SPYSTR_MESSAGE[] MDEF("message"); BEG const char __SPYSTR_STATUS[] MDEF("status"); BEG const char __SPYSTR_BOTNET[] MDEF("botnet"); -#define SPYSTR_RAWIRC (char*)__SPYSTR_RAWIRC -#define SPYSTR_MESSAGE (char*)__SPYSTR_MESSAGE -#define SPYSTR_STATUS (char*)__SPYSTR_STATUS -#define SPYSTR_BOTNET (char*)__SPYSTR_BOTNET +#define SPYSTR_RAWIRC __SPYSTR_RAWIRC +#define SPYSTR_MESSAGE __SPYSTR_MESSAGE +#define SPYSTR_STATUS __SPYSTR_STATUS +#define SPYSTR_BOTNET __SPYSTR_BOTNET + +#ifdef URLCAPTURE +BEG const char __SPYSTR_URL[] MDEF("url"); +#define SPYSTR_URL __SPYSTR_URL +#endif /* URLCAPTURE */ BEG const char STR_MECHRESET[] MDEF("MECHRESET="); @@ -110,7 +115,6 @@ BEG User __internal_users[2]; * (functions that do not call any other non-trivial functions) */ BEG char gsockdata[MAXLEN]; - BEG char nick_buf[MAXHOSTLEN]; BEG char nuh_buf[NUHLEN]; @@ -139,10 +143,6 @@ BEG Alias *aliaslist MDEF(NULL); #endif /* ALIAS */ -#ifdef UPTIME -BEG char *defaultuptimehost MDEF("uptime.energymech.net"); -#endif /* UPTIME */ - #ifdef BOTNET BEG const char UNKNOWNATUNKNOWN[] MDEF("unknown@unknown"); @@ -191,11 +191,17 @@ BEG Note *notelist MDEF(NULL); #endif /* NOTE */ -#ifdef SCRIPTING +#ifdef RAWDNS -BEG Hook *hooklist MDEF(NULL); +BEG dnsList *dnslist MDEF(NULL); +BEG dnsAuthority *dnsroot MDEF(NULL); +BEG struct in_addr ia_ns[MAX_NAMESERVERS]; +BEG struct in_addr ia_default; -#endif /* SCRIPTING */ +#ifdef SESSION +BEG Strp *dnsrootfiles MDEF(NULL); +#endif /* SESSION */ +#endif /* RAWDNS */ #ifdef REDIRECT @@ -211,6 +217,12 @@ LS struct #endif /* REDIRECT */ +#ifdef SCRIPTING + +BEG Hook *hooklist MDEF(NULL); + +#endif /* SCRIPTING */ + #ifdef SEEN BEG char *seenfile MDEF(NULL); /* proc var */ @@ -237,9 +249,17 @@ BEG ulong uptimeip MDEF((ulong)-1); BEG ulong uptimecookie; BEG ulong uptimeregnr MDEF(0); BEG time_t uptimelast MDEF(0); +BEG const char *defaultuptimehost MDEF("uptime.energymech.net"); #endif /* UPTIME */ +#ifdef URLCAPTURE + +BEG int urlhistmax MDEF(20); /* proc var */ +BEG Strp *urlhistory MDEF(NULL); + +#endif /* URLCAPTURE */ + #ifdef WEB BEG int websock MDEF(-1); @@ -247,17 +267,6 @@ BEG int webport MDEF(0); #endif /* WEB */ -#ifdef RAWDNS - -BEG dnsList *dnslist MDEF(NULL); -BEG dnsAuthority *dnsroot MDEF(NULL); -BEG struct in_addr ia_ns[MAX_NAMESERVERS]; -BEG struct in_addr ia_default; - -#ifdef SESSION -BEG Strp *dnsrootfiles MDEF(NULL); -#endif /* SESSION */ -#endif /* RAWDNS */ #ifndef I_HAVE_A_LEGITIMATE_NEED_FOR_MORE_THAN_4_BOTS diff --git a/src/greet.c b/src/greet.c index c8b657e..4e3132b 100644 --- a/src/greet.c +++ b/src/greet.c @@ -130,7 +130,7 @@ void do_greet(COMMAND_ARGS) { if (isfile) { - if (!is_safepath(rest)) + if (is_safepath(rest,FILE_MUST_EXIST) != FILE_IS_SAFE) goto usage; } diff --git a/src/h.h b/src/h.h index 0ac80b8..f9fcb08 100644 --- a/src/h.h +++ b/src/h.h @@ -1,7 +1,7 @@ /* EnergyMech, IRC bot software - Copyright (c) 1997-2009 proton + Copyright (c) 1997-2018 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 @@ -107,9 +107,9 @@ #endif /* DEBUG */ -LS Chan *find_channel(char *, int) __attr(CORE_SEG, __regparm (2) ); -LS Chan *find_channel_ac(char *) __attr(CORE_SEG, __regparm (1) ); -LS Chan *find_channel_ny(char *) __attr(CORE_SEG, __regparm (1) ); +LS Chan *find_channel(const char *, int) __attr(CORE_SEG, __regparm (2) ); +LS Chan *find_channel_ac(const char *) __attr(CORE_SEG, __regparm (1) ); +LS Chan *find_channel_ny(const char *) __attr(CORE_SEG, __regparm (1) ); LS ChanUser *find_chanuser(Chan *, const char *) __attr(CORE_SEG, __regparm (2) ); LS Client *find_client(const char *) __page(CORE_SEG); LS Mech *add_bot(int, char *) __page(CORE_SEG); @@ -121,13 +121,13 @@ LS Shit *add_shit(char *, char *, char *, char *, int, int) __page(CMD1_SEG); LS Shit *find_shit(const char *, const char *) __page(CORE_SEG); LS Shit *get_shituser(char *, char *) __page(CORE_SEG); LS User *add_user(char *, char *, int) __page(CFG1_SEG); -LS User *find_handle(char *) __page(CORE_SEG); +LS User *find_handle(const char *) __page(CORE_SEG); LS User *get_authuser(char *, char *) __page(CORE_SEG); LS User *get_user(const char *, const char *) __page(CORE_SEG); LS int get_authaccess(char *, char *) __page(CORE_SEG); LS int get_protaction(Chan *, char *) __page(CORE_SEG); LS int get_shitaction(const char *, const char *) __page(CORE_SEG); -LS int get_useraccess(char *, char *) __page(CORE_SEG); +LS int get_useraccess(const char *, const char *) __page(CORE_SEG); LS int get_maxaccess(const char *) __page(CORE_SEG); LS int Strcasecmp(const char *, const char *) __att2(CORE_SEG, const, __regparm (2) ); @@ -135,7 +135,7 @@ LS int Strcmp(const char *, const char *) __att2(CORE_SEG, const, __regparm (2 LS char *Strcat(char *, const char *) __attr(CORE_SEG, __regparm (2) ); LS char *Strchr(const char *, int) __att2(CORE_SEG, const, __regparm (2) ); LS char *Strcpy(char *, const char *) __attr(CORE_SEG, __regparm (2) ); -LS char *Strdup(char *) __page(CORE_SEG); +LS char *Strdup(const char *) __attr(CORE_SEG, __regparm (1) ); LS void Strncpy(char *, const char *, int) __attr(CORE_SEG, __regparm (3) ); LS char *chop(char **) __attr(CORE_SEG, __regparm (1) ); LS int get_number(const char *) __page(CORE_SEG); @@ -214,7 +214,7 @@ LS const int Strlen2(const char *, const char *) __attr(CORE_SEG, __regparm (2) LS int matches(const char *, const char *) __att2(CORE_SEG, const, __regparm (2) ); LS int num_matches(const char *, const char *) __att2(CORE_SEG, const, __regparm (2) ); LS int a2i(char *) __attr(CORE_SEG, __regparm (1) ); -LS int is_safepath(const char *) __page(CORE_SEG); +LS int is_safepath(const char *, int) __attr(CORE_SEG, __regparm (2) ); LS void afmt(char *, const char *, const char *) __page(CMD1_SEG); LS void aucheck(User *) __attr(CORE_SEG, __regparm (1) ); @@ -398,6 +398,9 @@ LS void parse_mode(char *, char *) __page(CORE_SEG); LS void parse_notice(char *, char *) __page(CORE_SEG); LS void parse_part(char *, char *) __page(CORE_SEG); LS void parse_ping(char *, char *) __page(CORE_SEG); +#ifdef URLCAPTURE +LS void urlcapture(const char *) __page(CORE_SEG); +#endif /* URLCAPTURE */ LS void parse_privmsg(char *, char *) __page(CORE_SEG); LS void parse_quit(char *, char *) __page(CORE_SEG); LS void parse_topic(char *, char *) __page(CMD1_SEG); @@ -772,6 +775,13 @@ LS void uptime_death(int) __page(RARE_SEG); /* rare */ #endif /* UPTIME */ +#ifdef URLCAPTURE + +LS void urlcapture(const char *) __page(CORE_SEG); +LS void do_urlhist(COMMAND_ARGS) __page(CMD1_SEG); + +#endif /* ifdef URLCAPTURE */ + /* * WEB prototypes */ diff --git a/src/help.c b/src/help.c index 8b291dd..29998a0 100644 --- a/src/help.c +++ b/src/help.c @@ -182,7 +182,7 @@ help_loop: /* * We dont want to show help for "../../../../../../etc/passwd" */ - if (!is_safepath(line)) + if (is_safepath(line,FILE_MUST_EXIST) != FILE_IS_SAFE) #ifdef DEBUG { debug("(do_help) unsafe help filename (%s), exiting\n",line); diff --git a/src/hostinfo.c b/src/hostinfo.c index b0157d6..0a0acb2 100644 --- a/src/hostinfo.c +++ b/src/hostinfo.c @@ -31,6 +31,12 @@ #include +/*---Help:HOSTINFO:(no arguments) + +Equivalent to ``uname -orm'' + +See also: meminfo, cpuinfo +*/ void do_hostinfo(COMMAND_ARGS) { struct utsname un; @@ -94,6 +100,19 @@ int parse_proc_status(char *line) return(FALSE); } +/*---Help:MEMINFO:(no arguments) + +Will display memory usage of the energymech process. + +VM Virtual size, size if everything was loaded into memory) +RSS Resident set size, physical memory actually in use right now. + Code Memory allocated for code + Data Memory allocated for data + Libs Memory used by shared libraries + Stack Memory allocated for stack + +See also: hostinfo, cpuinfo +*/ void do_meminfo(COMMAND_ARGS) { char fn[64]; @@ -113,6 +132,10 @@ void do_meminfo(COMMAND_ARGS) vmsize,vmpeak,vmrss,vmexe,vmdata,vmlib,vmstk); } +/*---Help:CPUINFO:(no arguments) + +See also: hostinfo, meminfo +*/ void do_cpuinfo(COMMAND_ARGS) { } diff --git a/src/main.c b/src/main.c index 33ab3a9..a4d8fc4 100644 --- a/src/main.c +++ b/src/main.c @@ -1,7 +1,7 @@ /* EnergyMech, IRC bot software - Parts Copyright (c) 1997-2009 proton + Parts Copyright (c) 1997-2018 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 @@ -774,6 +774,7 @@ int main(int argc, char **argv, char **envp) __attribute__ ((__sect(INIT_SEG))); #endif int main(int argc, char **argv, char **envp) { + struct stat st; char *opt; int do_fork = TRUE; int versiononly = FALSE; @@ -786,15 +787,14 @@ int main(int argc, char **argv, char **envp) _exit(1); } - { - struct stat st; // allocate temporary - - stat("..",&st); - parent_inode = st.st_ino; // used for is_safepath() - } + stat("..",&st); + parent_inode = st.st_ino; // used for is_safepath() srand(now+getpid()); + /* + * Code to detect and recover after a RESET + */ while(*envp) { char *p1; diff --git a/src/mega.c b/src/mega.c index c70b3c3..bee8a1a 100644 --- a/src/mega.c +++ b/src/mega.c @@ -49,6 +49,7 @@ #include "toybox.c" #include "trivia.c" #include "uptime.c" +#include "urlcap.c" #include "user.c" #include "vars.c" #include "web.c" diff --git a/src/parse.c b/src/parse.c index fbb2710..bb92dd2 100644 --- a/src/parse.c +++ b/src/parse.c @@ -1,7 +1,7 @@ /* EnergyMech, IRC bot software - Parts Copyright (c) 1997-2009 proton + Parts Copyright (c) 1997-2018 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 @@ -354,6 +354,9 @@ void parse_privmsg(char *from, char *rest) { ChanUser *cu; char *to,*channel; +#ifdef URLCAPTURE + const char *src; +#endif /* URLCAPTURE */ to = chop(&rest); if (*rest == ':') @@ -404,6 +407,24 @@ void parse_privmsg(char *from, char *rest) if (CurrentChan && CurrentChan->stats) CurrentChan->stats->privmsg++; #endif /* STATS */ +#ifdef URLCAPTURE + src = rest; + while(*src) + { + if (tolowertab[*src] == 'h') + { + if (tolowertab[src[1]] == 't' && tolowertab[src[2]] == 't' && tolowertab[src[3]] == 'p') + { + if ((src[4] == ':') || // "http:" + (tolowertab[src[4]] == 's' && src[5] == ':')) // "https:" + { + urlcapture(src); + } + } + } + src++; + } +#endif /* URLCAPTURE */ on_msg(from,to,rest); } diff --git a/src/redirect.c b/src/redirect.c index d89f64e..9aec244 100644 --- a/src/redirect.c +++ b/src/redirect.c @@ -1,7 +1,7 @@ /* EnergyMech, IRC bot software - Copyright (c) 1997-2004 proton + Copyright (c) 1997-2018 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 @@ -78,7 +78,7 @@ int begin_redirect(char *from, char *args) to_user(from,"Missing name for redirect."); return(-1); } - if (!is_safepath(nick)) + if (is_safepath(nick,FILE_MAY_EXIST) != FILE_IS_SAFE) // redirect output is appended { to_user(from,"Bad filename."); return(-1); diff --git a/src/settings.h b/src/settings.h index 9ad9f5a..26a295c 100644 --- a/src/settings.h +++ b/src/settings.h @@ -1,7 +1,7 @@ /* EnergyMech, IRC bot software - Copyright (c) 2001-2009 proton + Copyright (c) 2001-2018 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 @@ -76,73 +76,76 @@ LS const Setting VarName[SIZE_VARS] = /* * all global variables */ -/* TYPE UACCES MIN DEFAULT NAME MAX */ -{ INT_GLOBAL, 40, 0, ZERO, "AAWAY", 1440 }, /* set auto-away after ___ minutes */ -{ STR_GLOBAL, 90, 0, VNULL, "ALTNICK" }, /* alternative nick */ +/* TYPE UACCES MIN DEFAULT NAME MAX */ +{ INT_GLOBAL, 40, 0, ZERO, "AAWAY", 1440 }, /* set auto-away after ___ minutes */ +{ STR_GLOBAL, 90, 0, VNULL, "ALTNICK" }, /* alternative nick */ #ifdef BOTNET -{ TOG_PROC, 90, 0, TOGPROC(autolink), "AUTOLINK", 1 }, /* establish links automagically */ +{ TOG_PROC, 90, 0, TOGPROC(autolink), "AUTOLINK", 1 }, /* establish links automagically */ #endif /* BOTNET */ #ifdef BOUNCE -{ INT_PROC, 100, 0, INTPROC(bounce_port), "BNCPORT", 65535, (&new_port_bounce) }, /* irc proxy port to listen on */ +{ INT_PROC, 100, 0, INTPROC(bounce_port), "BNCPORT", 65535, (&new_port_bounce) }, /* irc proxy port to listen on */ #endif /* BOUNCE */ -{ TOG_GLOBAL, 90, 0, INTCAST(1), "CC", 1 }, /* require command char */ -{ CHR_GLOBAL, 90, 1, CMDCHAR, "CMDCHAR", 255 }, /* command char */ +{ TOG_GLOBAL, 90, 0, INTCAST(1), "CC", 1 }, /* require command char */ +{ CHR_GLOBAL, 90, 1, CMDCHAR, "CMDCHAR", 255 }, /* command char */ #ifdef CTCP -{ TOG_GLOBAL, 90, 0, INTCAST(1), "CTCP", 1 }, /* ctcp replies enable */ +{ TOG_GLOBAL, 90, 0, INTCAST(1), "CTCP", 1 }, /* ctcp replies enable */ #endif /* CTCP */ -{ INT_PROC, 100, 10, INTPROC(ctimeout), "CTIMEOUT", 3600 }, /* how long to wait between connect attempts */ +{ INT_PROC, 100, 10, INTPROC(ctimeout), "CTIMEOUT", 3600 }, /* how long to wait between connect attempts */ #ifdef DCC_FILE -{ INT_GLOBAL, 80, 0, ZERO, "DCCANON", 100 }, /* anonymous (non user) DCC slots */ -{ STR_GLOBAL, 80, 0, VNULL, "DCCFILES" }, /* string with space separated masks for auto-accepted filenames */ -{ INT_GLOBAL, 80, 0, INTCAST(4), "DCCUSER", 100 }, /* user DCC slots */ +{ INT_GLOBAL, 80, 0, ZERO, "DCCANON", 100 }, /* anonymous (non user) DCC slots */ +{ STR_GLOBAL, 80, 0, VNULL, "DCCFILES" }, /* string with space separated masks for auto-accepted filenames */ +{ INT_GLOBAL, 80, 0, INTCAST(4), "DCCUSER", 100 }, /* user DCC slots */ #endif /* DCC_FILE */ -{ TOG_GLOBAL, 80, 0, ZERO, "ENFPASS", 1 }, /* disallow users with no passwords */ -{ STR_GLOBAL, 90, 0, VNULL, "IDENT" }, /* register with this in the `user' field */ -{ STR_GLOBAL, 90, 0, VNULL, "IRCNAME" }, /* register with this in the `real name' field */ +{ TOG_GLOBAL, 80, 0, ZERO, "ENFPASS", 1 }, /* disallow users with no passwords */ +{ STR_GLOBAL, 90, 0, VNULL, "IDENT" }, /* register with this in the `user' field */ +{ STR_GLOBAL, 90, 0, VNULL, "IRCNAME" }, /* register with this in the `real name' field */ #ifdef NOTIFY -{ INT_GLOBAL, 80, 10, INTCAST(30), "ISONDELAY", 600 }, /* seconds between each ISON */ +{ INT_GLOBAL, 80, 10, INTCAST(30), "ISONDELAY", 600 }, /* seconds between each ISON */ #endif /* NOTIFY */ #ifdef BOTNET -{ STR_PROC, 90, 0, STRPROC(linkpass), "LINKPASS" }, /* local process linkpass */ -{ INT_PROC, 100, 0, INTPROC(linkport), "LINKPORT", 65535 }, /* listen on for botnet connections */ +{ STR_PROC, 90, 0, STRPROC(linkpass), "LINKPASS" }, /* local process linkpass */ +{ INT_PROC, 100, 0, INTPROC(linkport), "LINKPORT", 65535 }, /* listen on for botnet connections */ #endif /* BOTNET */ -{ INT_GLOBAL, 80, 1, INTCAST(3), "MODES", 20 }, /* max number of channel modes to send */ +{ INT_GLOBAL, 80, 1, INTCAST(3), "MODES", 20 }, /* max number of channel modes to send */ #ifdef BOTNET -{ TOG_GLOBAL, 90, 0, INTCAST(1), "NETUSERS", 1 }, /* this bot accepts shared users (on by default) */ +{ TOG_GLOBAL, 90, 0, INTCAST(1), "NETUSERS", 1 }, /* this bot accepts shared users (on by default) */ #endif /* BOTNET */ -{ TOG_GLOBAL, 80, 0, ZERO, "NOIDLE", 1 }, /* dont idle */ +{ TOG_GLOBAL, 80, 0, ZERO, "NOIDLE", 1 }, /* dont idle */ #ifdef NOTIFY -{ STR_GLOBAL, 80, 0, VNULL, "NOTIFYFILE" }, /* read notify settings from */ +{ STR_GLOBAL, 80, 0, VNULL, "NOTIFYFILE" }, /* read notify settings from */ #endif /* NOTIFY */ -{ TOG_GLOBAL, 90, 0, ZERO, "ONOTICE", 1 }, /* ircd has /notice @#channel */ +{ TOG_GLOBAL, 90, 0, ZERO, "ONOTICE", 1 }, /* ircd has /notice @#channel */ #ifdef TRIVIA -{ CHR_PROC, 80, 0, CHRPROC(triv_qchar), "QCHAR" }, /* use as mask char when displaying answer */ -{ INT_PROC, 80, 1, INTPROC(triv_qdelay), "QDELAY", 3600 }, /* seconds between each question */ -{ STR_PROC, 80, 0, STRPROC(triv_qfile), "QFILE" }, /* load questions from */ +{ CHR_PROC, 80, 0, CHRPROC(triv_qchar), "QCHAR" }, /* use as mask char when displaying answer */ +{ INT_PROC, 80, 1, INTPROC(triv_qdelay), "QDELAY", 3600 }, /* seconds between each question */ +{ STR_PROC, 80, 0, STRPROC(triv_qfile), "QFILE" }, /* load questions from */ #endif /* TRIVIA */ #ifdef CTCP -{ TOG_GLOBAL, 80, 0, ZERO, "RF", 1 }, /* random ctcp finger reply */ -{ TOG_GLOBAL, 80, 0, ZERO, "RV", 1 }, /* random ctcp version reply */ +{ TOG_GLOBAL, 80, 0, ZERO, "RF", 1 }, /* random ctcp finger reply */ +{ TOG_GLOBAL, 80, 0, ZERO, "RV", 1 }, /* random ctcp version reply */ #endif /* CTCP */ #ifdef SEEN -{ STR_PROC, 90, 0, STRPROC(seenfile), "SEENFILE" }, /* load/save seen database from */ +{ STR_PROC, 90, 0, STRPROC(seenfile), "SEENFILE" }, /* load/save seen database from */ #endif /* SEEN */ -{ STR_GLOBAL, 80, 0, VNULL, "SERVERGROUP" }, /* connect bot to a certain group of servers */ -{ TOG_GLOBAL, 90, 0, ZERO, "SPY", 1 }, /* send info about executed commands to status channel */ -{ STR_GLOBAL, 90, 0, VNULL, "UMODES" }, /* send these modes on connect */ +{ STR_GLOBAL, 80, 0, VNULL, "SERVERGROUP" }, /* connect bot to a certain group of servers */ +{ TOG_GLOBAL, 90, 0, ZERO, "SPY", 1 }, /* send info about executed commands to status channel */ +{ STR_GLOBAL, 90, 0, VNULL, "UMODES" }, /* send these modes on connect */ #ifdef UPTIME -{ STR_PROC, 100, 0, STRPROC(uptimehost), "UPHOST" }, /* send uptime packets to */ -{ STR_PROC, 100, 0, STRPROC(uptimenick), "UPNICK" }, /* send as identifier instead of bots nick */ -{ INT_PROC, 100, 0, INTPROC(uptimeport), "UPPORT", 65535 }, /* send packets to port */ +{ STR_PROC, 100, 0, STRPROC(uptimehost), "UPHOST" }, /* send uptime packets to */ +{ STR_PROC, 100, 0, STRPROC(uptimenick), "UPNICK" }, /* send as identifier instead of bots nick */ +{ INT_PROC, 100, 0, INTPROC(uptimeport), "UPPORT", 65535 }, /* send packets to port */ +#ifdef URLCAPTURE +{ INT_PROC, 100, 0, INTPROC(urlhistmax), "URLHIST", 100 }, /* max # of url's to keep in history */ +#endif /* URLCAPTURE */ #endif /* UPTIME */ -{ STR_GLOBAL, 90, 0, VNULL, "USERFILE" }, /* what file to load/save userlist from/to */ -{ STR_GLOBAL, 90, 0, VNULL, "VIRTUAL", 0, (&var_resolve_host) }, /* visual host */ +{ STR_GLOBAL, 90, 0, VNULL, "USERFILE" }, /* what file to load/save userlist from/to */ +{ STR_GLOBAL, 90, 0, VNULL, "VIRTUAL", 0, (&var_resolve_host) }, /* visual host */ #ifdef WEB -{ INT_PROC, 100, 0, INTPROC(webport), "WEBPORT", 65535 }, /* httpd should listen on... */ +{ INT_PROC, 100, 0, INTPROC(webport), "WEBPORT", 65535 }, /* httpd should listen on... */ #endif /* WEB */ #ifdef WINGATE -{ STR_GLOBAL, 90, 0, VNULL, "WINGATE", 0, (&var_resolve_host) }, /* wingate hostname */ -{ INT_GLOBAL, 90, 0, ZERO, "WINGPORT", 65535 }, /* wingate port */ +{ STR_GLOBAL, 90, 0, VNULL, "WINGATE", 0, (&var_resolve_host) }, /* wingate hostname */ +{ INT_GLOBAL, 90, 0, ZERO, "WINGPORT", 65535 }, /* wingate port */ #endif /* WINGATE */ { 0, }}; diff --git a/src/spy.c b/src/spy.c index 3af27cd..4f6d16c 100644 --- a/src/spy.c +++ b/src/spy.c @@ -1,7 +1,7 @@ /* EnergyMech, IRC bot software - Parts Copyright (c) 1997-2004 proton + Parts Copyright (c) 1997-2018 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 @@ -30,7 +30,7 @@ #ifdef DEBUG -LS const char SPY_DEFS[7][12] = +LS const char SPY_DEFS[][12] = { "SPY_FILE", "SPY_CHANNEL", @@ -38,7 +38,10 @@ LS const char SPY_DEFS[7][12] = "SPY_STATUS", "SPY_MESSAGE", "SPY_RAWIRC", - "SPY_BOTNET" + "SPY_BOTNET", +#ifdef URLCAPTURE + "SPY_URL", +#endif /* URLCAPTURE */ }; #endif /* DEBUG */ @@ -161,7 +164,7 @@ void spy_typecount(Mech *bot) struct { - char *idstring; + const char *idstring; int typenum; } spy_source_list[] = @@ -170,13 +173,20 @@ struct { SPYSTR_MESSAGE, SPY_MESSAGE }, { SPYSTR_RAWIRC, SPY_RAWIRC }, { SPYSTR_BOTNET, SPY_BOTNET }, +#ifdef URLCAPTURE +{ SPYSTR_URL, SPY_URL }, +#endif /* URLCAPTURE */ { NULL, 0 }, }; -int spy_source(char *from, int *t_src, char **src) +int spy_source(char *from, int *t_src, const char **src) { int i; +#ifdef DEBUG + debug("(spy_source) t_src %i, src %s\n",*t_src,*src); +#endif /* ifdef DEBUG */ + for(i=0;spy_source_list[i].idstring;i++) { if (!Strcasecmp(*src,spy_source_list[i].idstring)) @@ -198,6 +208,31 @@ int spy_source(char *from, int *t_src, char **src) * */ +/*---Help:SPY:[STATUS|MESSAGE|RAWIRC|URL|[guid:|botnick:] [channel|> filename] + +Spy on a certain source of messages. When you join DCC chat, +the STATUS source is added by default as a spy source for you. +If no arguments are given, the current list of active spy +channels is shown. Output is not line buffered and can cause +excess flood if not careful. + + (sources) + STATUS Status messages. + MESSAGE Pivate messages that the bot receives. + RAWIRC Lines received from irc server before processing. + URL URLs seen by the bot. + guid: Messages from a bot specified by guid. + botnick: Messages from a bot specified by nick. + channel Activities on the specified channel. + + (destinations) + (none) Send output to you (default). + channel Send output to the specified channel. + >file Send output to file. Lines are appended to the end of the file. + This file needs to exist before logging to it. + +See also: rspy +*/ void do_spy(COMMAND_ARGS) { /* @@ -205,10 +240,10 @@ void do_spy(COMMAND_ARGS) */ Spy *spy; Mech *backup,*destbot; - char *src,*dest; + const char *src; + char *dest; int t_src,t_dest; - int sz; - int guid; + int sz,r,guid; if (!*rest) { @@ -291,9 +326,9 @@ guid_ok: else { sz = spy_source(from,&t_src,&src); - if (sz < 0) + if (sz < 0) // user has insufficient access to source goto spy_usage; - if (sz < cmdaccess) + if (sz < cmdaccess) // user has less access relative to source than the command level of SPY return; } @@ -304,6 +339,7 @@ guid_ok: */ if (*dest == '>') { + // accept both ">file" and "> file" dest++; if (!*dest) { @@ -314,8 +350,16 @@ guid_ok: /* * Dont just open anything. */ - if (!is_safepath(dest)) + r = is_safepath(dest,FILE_MAY_EXIST); + if (r != FILE_IS_SAFE) +#ifdef DEBUG + { + debug("(do_spy) Filename \"%s\" was deemed unsafe (%i)\n",dest,r); goto spy_usage; + } +#else + goto spy_usage; +#endif /* DEBUG */ t_dest = SPY_FILE; goto spy_dest_ok; } @@ -384,7 +428,7 @@ spy_dest_ok: if (t_src == SPY_CHANNEL) { - Strcpy(spy->src,src); + Strcpy((char*)spy->src,src); } else { @@ -434,7 +478,8 @@ void do_rspy(COMMAND_ARGS) * on_msg checks: CARGS */ Spy *spy,**pspy; - char *src,*dest,*tmp; + const char *src; + char *dest,*tmp; int t_src,t_dest; int n; @@ -468,18 +513,11 @@ rspy_usage: goto rspy_usage; } /* - * Dont just open anything. + * this is about removing an existing spy channel + * filename does not need to be checked because + * - if its a bogus filename, it wont match any open spy channels + * - if its a matching filename, its going to be removed right now */ - if (!is_safepath(dest)) -#ifdef NEWBIE - { - usage(from); - to_user(from,"File/path does not exist or is inaccessible"); - return; - } -#else - goto rspy_usage; -#endif /* NEWBIE */ t_dest = SPY_FILE; goto rspy_dest_ok; } diff --git a/src/structs.h b/src/structs.h index 37b31b8..e70ff08 100644 --- a/src/structs.h +++ b/src/structs.h @@ -469,7 +469,7 @@ typedef struct Spy Client *dcc; int destbot; - char *src; + const char *src; char *dest; char p[2]; diff --git a/src/uptime.c b/src/uptime.c index 42c1117..9bfcaa8 100644 --- a/src/uptime.c +++ b/src/uptime.c @@ -1,7 +1,7 @@ /* EnergyMech, IRC bot software - Copyright (c) 1997-2004 proton + Copyright (c) 1997-2018 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 @@ -101,7 +101,7 @@ void send_uptime(int type) const char *server,*nick; int sz; - if (uptimeport == 0) + if (uptimehost == NULL || uptimeport == 0) return; #ifdef RAWDNS diff --git a/src/urlcap.c b/src/urlcap.c new file mode 100644 index 0000000..bb4b294 --- /dev/null +++ b/src/urlcap.c @@ -0,0 +1,120 @@ +/* + + EnergyMech, IRC bot software + Copyright (c) 2018 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 URLCAP_C +#include "config.h" + +#ifdef URLCAPTURE + +#include "defines.h" +#include "structs.h" +#include "global.h" +#include "h.h" +#include "text.h" + +__page(CORE_SEG) +void urlcapture(const char *rest) +{ + Strp *sp,*nx; + char *dest,url[MSGLEN]; + int n; + + dest = url; + while(*rest && *rest != ' ' && dest < url+MSGLEN-1) + *(dest++) = *(rest++); + *dest = 0; + +#ifdef DEBUG + debug("(urlcapture) URL = \"%s\"\n",url); +#endif /* ifdef DEBUG */ + + send_spy(SPYSTR_URL,"%s",url); + + if ((n = urlhistmax)) + { + set_mallocdoer(urlcapture); + sp = (Strp*)Calloc(sizeof(Strp) + strlen(url)); + Strcpy(sp->p,url); + sp->next = urlhistory; + urlhistory = sp; + + for(sp=urlhistory;sp;sp=sp->next) + { + if (n <= 0) + { + do + { + nx = sp->next; + Free((char**)&sp); + sp = nx; + } + while(sp); + } + n--; + } + } +} + +/* + * + * Commands associated with URLCAPTURE + * + */ + +/*---Help:URLHIST:[max] + +Display a list of URLs seen by the bot in order most recent to oldest. + + [max] Maximum number of URLs to display. +*/ +__page(CMD1_SEG) +void do_urlhist(COMMAND_ARGS) +{ + Strp *sp; + char *thenum; + int n,maxnum; + + if (urlhistory == NULL) + { + to_user(from,"No URLs recorded."); + return; + } + + if (!rest || !*rest) + maxnum = urlhistmax; + else + { + thenum = chop(&rest); + maxnum = a2i(thenum); + } + if ((maxnum < 1) || (maxnum > urlhistmax)) + usage(from); /* usage for CurrentCmd->name */ + + n = 1; + for(sp=urlhistory;sp;sp=sp->next) + { + if (n > maxnum) + break; + to_user(from,"[%i] %s",n,sp->p); + n++; + } +} + +#endif /* ifdef URLCAPTURE */ diff --git a/src/user.c b/src/user.c index 92b50cc..b878570 100644 --- a/src/user.c +++ b/src/user.c @@ -738,7 +738,7 @@ User *add_user(char *handle, char *pass, int axs) /* * find the user record for a named handle */ -User *find_handle(char *handle) +User *find_handle(const char *handle) { User *user; @@ -803,7 +803,7 @@ User *get_user(const char *userhost, const char *channel) /* * highest channel on a given channel */ -int get_useraccess(char *userhost, char *channel) +int get_useraccess(const char *userhost, const char *channel) { User *user;