*/
#include "trojanscan.h"
+#include "../lib/strlfunc.h"
+#include "../lib/version.h"
+
+MODULE_VERSION(TROJANSCAN_VERSION " / $Id: trojanscan.c 663 2006-05-16 17:27:36Z newserv $")
void _init() {
trojanscan_cmds = newcommandtree();
addcommandtotree(trojanscan_cmds, "rehash", TROJANSCAN_ACL_WEBSITE, 0, &trojanscan_rehash);
- addcommandtotree(trojanscan_cmds, "cat", TROJANSCAN_ACL_CAT | TROJANSCAN_ACL_OPER, 1, &trojanscan_cat);
+ addcommandtotree(trojanscan_cmds, "cat", TROJANSCAN_ACL_OPER, 1, &trojanscan_cat);
addcommandtotree(trojanscan_cmds, "reschedule", TROJANSCAN_ACL_DEVELOPER | TROJANSCAN_ACL_OPER, 0, &trojanscan_reschedule);
}
trojanscan_database_query("CREATE TABLE phrases (id INT(10) PRIMARY KEY AUTO_INCREMENT, wormid INT(10) NOT NULL, phrase TEXT NOT NULL, priority INT(10) DEFAULT 0 NOT NULL, dateadded int(10))");
- trojanscan_database_query("CREATE TABLE worms (id INT(10) PRIMARY KEY AUTO_INCREMENT, wormname TEXT NOT NULL, glinetype INT DEFAULT 0, data text, hitmsgs BOOL DEFAULT 1, hitchans BOOL DEFAULT 0, epidemic BOOL DEFAULT 0)");
+ trojanscan_database_query("CREATE TABLE worms (id INT(10) PRIMARY KEY AUTO_INCREMENT, wormname TEXT NOT NULL, glinetype INT DEFAULT 0, data text, hitmsgs BOOL DEFAULT 1, hitchans BOOL DEFAULT 0, epidemic BOOL DEFAULT 0, privinfo text)");
trojanscan_database_query("CREATE TABLE logs (id INT(10) PRIMARY KEY AUTO_INCREMENT, userid INT(10) NOT NULL, act TEXT NOT NULL, description TEXT NOT NULL, ts TIMESTAMP)");
trojanscan_database_query("CREATE TABLE channels (id INT(10) PRIMARY KEY AUTO_INCREMENT, channel VARCHAR(%d) NOT NULL, exempt BOOL DEFAULT 0)", CHANNELLEN);
trojanscan_database_query("CREATE TABLE users (id INT(10) PRIMARY KEY AUTO_INCREMENT, authname VARCHAR(%d) NOT NULL, authlevel TINYINT(4) NOT NULL)", ACCOUNTLEN);
trojanscan_database_query("CREATE TABLE wwwlogs (id INT(10) PRIMARY KEY AUTO_INCREMENT, authid INT(10) NOT NULL, ip VARCHAR(15), action TEXT, ts TIMESTAMP)");
trojanscan_database_query("CREATE TABLE unknownlog (id INT(10) PRIMARY KEY AUTO_INCREMENT, data TEXT, user VARCHAR(%d) NOT NULL, ts TIMESTAMP)", NICKLEN+USERLEN+HOSTLEN+3);
- trojanscan_database_query("DELETE FROM settings WHERE setting = 'rehash'");
+ trojanscan_database_query("DELETE FROM settings");
trojanscan_database_query("INSERT INTO settings (setting, value) VALUES ('rehash','0')");
trojanscan_database_query("INSERT INTO settings (setting, value) VALUES ('changed','0')");
freesstring(dbport);
trojanscan_registerclones(NULL);
- trojanscan_initialschedule = scheduleoneshot(time(NULL) + 300, &trojanscan_fill_channels, NULL);
trojanscan_rehashschedule = scheduleoneshot(time(NULL) + 60, &trojanscan_rehash_schedule, NULL);
}
for(i=0;i<trojanscan_database.total_channels;i++)
freesstring(trojanscan_database.channels[i].name);
free(trojanscan_database.channels);
- for(i=0;i<trojanscan_database.total_phrases;i++)
- if (trojanscan_database.phrases[i].phrase) {
- free(trojanscan_database.phrases[i].phrase);
- free(trojanscan_database.phrases[i].hint);
- }
+ for(i=0;i<trojanscan_database.total_phrases;i++) {
+ if (trojanscan_database.phrases[i].phrase)
+ pcre_free(trojanscan_database.phrases[i].phrase);
+ if (trojanscan_database.phrases[i].hint)
+ pcre_free(trojanscan_database.phrases[i].hint);
+ }
free(trojanscan_database.phrases);
for(i=0;i<trojanscan_database.total_worms;i++)
freesstring(trojanscan_database.worms[i].name);
if (!(trojanscan_database.phrases[i].phrase = pcre_compile(sqlrow[1], PCRE_CASELESS, &error, &erroroffset, NULL))) {
Error("trojanscan", ERR_WARNING, "Error compiling expression %s at offset %d: %s", sqlrow[1], erroroffset, error);
} else {
- if ((trojanscan_database.phrases[i].hint = pcre_study(trojanscan_database.phrases[i].phrase, 0, &error))) {
+ trojanscan_database.phrases[i].hint = pcre_study(trojanscan_database.phrases[i].phrase, 0, &error);
+ if (error) {
Error("trojanscan", ERR_WARNING, "Error studying expression %s: %s", sqlrow[1], error);
- free(trojanscan_database.phrases[i].phrase);
+ pcre_free(trojanscan_database.phrases[i].phrase);
trojanscan_database.phrases[i].phrase = NULL;
}
}
void trojanscan_generateclone(void *arg) {
int i, loops = 0, modes = UMODE_XOPER | UMODE_INV;
char c_nick[NICKLEN+1], c_ident[USERLEN+1], c_host[HOSTLEN+1], c_real[REALLEN+1];
+ long fakeip;
i = (int)arg;
trojanscan_genident(c_ident, trojanscan_minmaxrand(4, TROJANSCAN_MMIN(8, USERLEN)));
if(trojanscan_hostmode) {
- trojanscan_generatehost(c_host, HOSTLEN);
+ trojanscan_generatehost(c_host, HOSTLEN, &fakeip);
if(!c_host[0])
- trojanscan_genhost(c_host, HOSTLEN);
+ trojanscan_genhost(c_host, HOSTLEN, &fakeip);
} else {
- trojanscan_genhost(c_host, HOSTLEN);
+ trojanscan_genhost(c_host, HOSTLEN, &fakeip);
}
trojanscan_generaterealname(c_real, REALLEN);
trojanscan_genreal(c_real, trojanscan_minmaxrand(15, TROJANSCAN_MMIN(50, REALLEN)));
trojanscan_swarm[i].clone = registerlocaluser(c_nick, c_ident, c_host, c_real, NULL, modes, &trojanscan_clonehandlemessages);
+ trojanscan_swarm[i].fakeip = fakeip;
+
if(trojanscan_swarm[i].clone && !trojanscan_swarm_created) {
nick *np = trojanscan_selectuser();
if(np) /* select a 'random' sign on time for whois generation */
trojanscan_generateclone((void *)i);
trojanscan_mainchanmsg("n: swarm (%d clones) created.", TROJANSCAN_CLONE_TOTAL);
trojanscan_swarm_created = 1;
+
+ trojanscan_initialschedule = scheduleoneshot(time(NULL) + 5, &trojanscan_fill_channels, NULL);
}
int trojanscan_status(void *sender, int cargc, char **cargv) {
if (trojanscan_database_num_rows(res) > 0) {
trojanscan_database_row sqlrow = trojanscan_database_fetch_row(res);
result = atoi(sqlrow[0]);
- strncpy(authname, sqlrow[1], sl);
+ strlcpy(authname, sqlrow[1], sl + 1);
}
trojanscan_database_free_result(res);
}
}
+/* hack hack hack */
+int trojanscan_nickbanned(trojanscan_clones *np, channel *cp) {
+ int ret;
+ long realip = np->clone->ipaddress;
+
+ np->clone->ipaddress = np->fakeip;
+
+ ret = nickbanned(np->clone, cp);
+
+ np->clone->ipaddress = realip;
+
+ return ret;
+}
+
struct trojanscan_realchannels *trojanscan_allocaterc(char *chan) {
struct trojanscan_realchannels *rc;
struct trojanscan_clones *clonep;
trojanscan_errorcode = 6;
return NULL;
}
- if(!nickbanned(clonep->clone, cp))
+ if(!trojanscan_nickbanned(clonep, cp))
break;
} while (--attempts_left > 0);
void trojanscan_watch_clone_update(struct trojanscan_prechannels *hp, int count) {
int i, j, marked;
struct trojanscan_prechannels *lp;
- struct trojanscan_templist *markedlist;
+ struct trojanscan_templist *markedlist = NULL;
if(count > 0) {
markedlist = (struct trojanscan_templist *)calloc(count, sizeof(struct trojanscan_templist));
for(i=0;i<trojanscan_activechans;i++) {
marked = 0;
- for(lp=hp,j=0;j<count&&lp;j++,lp=lp->next) {
- if(!markedlist[j].active && !lp->exempt && !ircd_strcmp(lp->name->content, trojanscan_chans[i].channel->content)) { /* we're already on the channel */
- if(trojanscan_chans[i].watch_clone) {
- markedlist[j].active = 1;
- markedlist[j].watch_clone = trojanscan_chans[i].watch_clone;
- lp->watch_clone = trojanscan_chans[i].watch_clone;
+ if(markedlist) {
+ for(lp=hp,j=0;j<count&&lp;j++,lp=lp->next) {
+ if(!markedlist[j].active && !lp->exempt && !ircd_strcmp(lp->name->content, trojanscan_chans[i].channel->content)) { /* we're already on the channel */
+ if(trojanscan_chans[i].watch_clone) {
+ markedlist[j].active = 1;
+ markedlist[j].watch_clone = trojanscan_chans[i].watch_clone;
+ lp->watch_clone = trojanscan_chans[i].watch_clone;
+ }
+ marked = 1;
+ break;
}
- marked = 1;
- break;
}
}
if(!marked && trojanscan_chans[i].watch_clone) {
}
}
+ if(!markedlist)
+ return;
+
for(j=0,lp=hp;j<count&&lp;j++,lp=lp->next) {
if((!markedlist[j].active || !markedlist[j].watch_clone) && !lp->exempt) {
channel *cp = findchannel(lp->name->content);
lp->watch_clone = trojanscan_selectclone(TROJANSCAN_WATCH_CLONES);
if(!lp->watch_clone)
break;
- if(!nickbanned(lp->watch_clone->clone, cp)) {
+ if(!trojanscan_nickbanned(lp->watch_clone, cp)) {
if(localjoinchannel(lp->watch_clone->clone, cp))
lp->watch_clone = NULL;
break;
if (worm->monitor) {
glining = 0;
usercount = -1;
- } else if (worm->glinehost) {
+ } else if (worm->glinehost && (hp->clonecount <= TROJANSCAN_MAX_HOST_GLINE)) {
snprintf(glinemask, sizeof(glinemask) - 1, "*@%s", trojanscan_iptostr(ip, sizeof(ip) - 1, sender->ipaddress));
usercount = hp->clonecount;
}
-
- /* if the host is >maxusers then it's a trusted host and we can gline by ident */
- if (worm->glineuser || (worm->glinehost && (usercount > trojanscan_maxusers))) {
+ else if (worm->glineuser || (worm->glinehost && hp->clonecount > TROJANSCAN_MAX_HOST_GLINE)) {
userbit = sender->ident;
if(userbit[0] == '~')
userbit++;
matchbuf[0] = 0;
trojanscan_mainchanmsg("m: t: %c u: %s!%s@%s%s%s w: %s %s%s", mt, sender->nick, sender->ident, sender->host->name->content, mt=='N'||mt=='M'?" #: ":"", mt=='N'||mt=='M'?chp->index->name->content:"", worm->name->content, matchbuf[0]?" --: ":"", matchbuf[0]?matchbuf:"");
- trojanscan_peonchanmsg("m: t: %c u: %s!%s@%s%s%s%s w: %s %s%s", mt, sender->nick, sender->ident, (IsHideHost(sender)&&IsAccount(sender))?sender->authname:sender->host->name->content, (IsHideHost(sender)&&IsAccount(sender))?"."HIS_HIDDENHOST:"", mt=='N'||mt=='M'?" #: ":"", mt=='N'||mt=='M'?chp->index->name->content:"", worm->name->content, matchbuf[0]?" --: ":"", matchbuf[0]?matchbuf:"");
+/* trojanscan_peonchanmsg("m: t: %c u: %s!%s@%s%s%s%s w: %s %s%s", mt, sender->nick, sender->ident, (IsHideHost(sender)&&IsAccount(sender))?sender->authname:sender->host->name->content, (IsHideHost(sender)&&IsAccount(sender))?"."HIS_HIDDENHOST:"", mt=='N'||mt=='M'?" #: ":"", mt=='N'||mt=='M'?chp->index->name->content:"", worm->name->content, matchbuf[0]?" --: ":"", matchbuf[0]?matchbuf:""); */
} else {
int glinetime = TROJANSCAN_FIRST_OFFENSE * frequency * (worm->epidemic?TROJANSCAN_EPIDEMIC_MULTIPLIER:1);
if(glinetime > 7 * 24)
trojanscan_database_query("INSERT INTO hits (nickname, ident, host, phrase, messagetype, glined) VALUES ('%s', '%s', '%s', %d, '%c', %d)", enick, eident, ehost, trojanscan_database.phrases[i].id, mt, glining);
trojanscan_database.glines++;
- irc_send("%s GL * +%s %d %d :You (%s!%s@%s) are infected with a trojan (%s), see %s%d for details - banned for %d hours\r\n", mynumeric->content, glinemask, glinetime * 3600, getnettime(), sender->nick, sender->ident, sender->host->name->content, worm->name->content, TROJANSCAN_URL_PREFIX, worm->id, glinetime);
+ irc_send("%s GL * +%s %d :You (%s!%s@%s) are infected with a trojan (%s), see %s%d for details - banned for %d hours\r\n", mynumeric->content, glinemask, glinetime * 3600, sender->nick, sender->ident, sender->host->name->content, worm->name->content, TROJANSCAN_URL_PREFIX, worm->id, glinetime);
trojanscan_mainchanmsg("g: *!%s t: %c u: %s!%s@%s%s%s c: %d w: %s%s f: %d", glinemask, mt, sender->nick, sender->ident, sender->host->name->content, mt=='N'||mt=='M'?" #: ":"", mt=='N'||mt=='M'?chp->index->name->content:"", usercount, worm->name->content, worm->epidemic?"(E)":"", frequency);
}
return;
}
- rj->clone = target;
+ rj->clone = rp->clone;
rj->next = trojanscan_schedulerejoins;
trojanscan_schedulerejoins = rj;
rj->rp->donotpart = 1; /* we were the last user on the channel, so we need to be VERY careful freeing it */
} else {
if(!rj->rp->donotpart && !rj->rp->kickedout) { /* check we're allowed to join channels (not killed), and we're the last one to join */
- if (nickbanned(rj->clone, cp)) {
+ if (trojanscan_nickbanned(rj->clone, cp)) {
rj->rp->donotpart = 1;
} else {
- localjoinchannel(rj->clone, cp);
+ localjoinchannel(rj->clone->clone, cp);
}
}
}
ptc[i] = '\0';
}
-void trojanscan_genhost(char *ptc, char size) {
+void trojanscan_genhost(char *ptc, char size, long *fakeip) {
int dots = trojanscan_minmaxrand(2, 5), i, dotexist = 0, cur;
while (!dotexist) {
}
}
ptc[i] = '\0';
+
+ *fakeip = (trojanscan_minmaxrand(0, 65535) << 16) | trojanscan_minmaxrand(0, 65535);
}
void trojanscan_genreal(char *ptc, char size) {
return NULL;
}
-void trojanscan_generatehost(char *buf, int maxsize) {
+host *trojanscan_selecthost(void) {
+ int target = trojanscan_minmaxrand(0, 500), loops = 150, j;
+ host *hp;
+ do {
+ for (j=trojanscan_minmaxrand(0, HOSTHASHSIZE-1);j<HOSTHASHSIZE;j++)
+ for(hp=hosttable[j];hp;hp=hp->next)
+ if (!--target)
+ return hp;
+ } while(--loops > 0);
+
+ return NULL;
+}
+
+void trojanscan_generatehost(char *buf, int maxsize, long *fakeip) {
if(TROJANSCAN_HOST_MODE == TROJANSCAN_STEAL_HOST) {
- nick *np;
+ host *hp;
int loops = 20;
+
buf[0] = '\0';
+
do {
- np = trojanscan_selectuser();
- if(np && !trojanscan_isip(np->host->name->content)) {
- strncpy(buf, np->host->name->content, maxsize);
+ hp = trojanscan_selecthost();
+ if(hp && (hp->clonecount <= TROJANSCAN_MAX_CLONE_COUNT) && !trojanscan_isip(hp->name->content)) {
+ strlcpy(buf, hp->name->content, maxsize + 1);
+ if(hp->nicks) {
+ *fakeip = hp->nicks->ipaddress;
+ } else {
+ *fakeip = (trojanscan_minmaxrand(0, 65535) << 16) | trojanscan_minmaxrand(0, 65535);
+ }
break;
}
} while(--loops > 0);
buf[a] = '\0';
free(choices);
free(lengths);
+
+ *fakeip = (trojanscan_minmaxrand(0, 65535) << 16) | trojanscan_minmaxrand(0, 65535);
}
}
nick *np = trojanscan_selectuser();
buf[0] = '\0';
if(np)
- strncpy(buf, np->ident, maxsize);
+ strlcpy(buf, np->ident, maxsize + 1);
}
void trojanscan_generaterealname(char *buf, int maxsize) {
nick *np = trojanscan_selectuser();
buf[0] = '\0';
if(np)
- strncpy(buf, np->realname->name->content, maxsize);
+ strlcpy(buf, np->realname->name->content, maxsize + 1);
}
void trojanscan_database_close(void) {