#include <sys/poll.h>
#include <sys/types.h>
#include <sys/socket.h>
+#include <signal.h>
#include <netdb.h>
#include "../core/error.h"
#include "../core/events.h"
#include "../localuser/localuserchannel.h"
#include "../core/nsmalloc.h"
#include "../lib/irc_ipv6.h"
+#include "../glines/glines.h"
MODULE_VERSION("")
int proxyscandospew(void *sender, int cargc, char **cargv);
int proxyscandoshowkill(void *sender, int cargc, char **cargv);
int proxyscandoscan(void *sender, int cargc, char **cargv);
+int proxyscandoscanfile(void *sender, int cargc, char **cargv);
int proxyscandoaddscan(void *sender, int cargc, char **cargv);
int proxyscandodelscan(void *sender, int cargc, char **cargv);
int proxyscandoshowcommands(void *sender, int cargc, char **cargv);
return 0;
}
+void ignorepipe(int signal_) {
+ signal(SIGPIPE, ignorepipe); /* HACK */
+}
+
void _init(void) {
sstring *cfgstr;
int ipbits[4];
+ signal(SIGPIPE, ignorepipe); /* HACK */
+
ps_start_ts = time(NULL);
ps_ready = 0;
ps_commands = NULL;
freesstring(cfgstr);
/* Max concurrent scans */
- cfgstr=getcopyconfigitem("proxyscan","maxscans","200",5);
+ cfgstr=getcopyconfigitem("proxyscan","maxscans","200",10);
maxscans=strtol(cfgstr->content,NULL,10);
freesstring(cfgstr);
addcommandtotree(ps_commands, "status", 0, 0, &proxyscandostatus);
addcommandtotree(ps_commands, "listopen", 0, 0, &proxyscandolistopen);
addcommandtotree(ps_commands, "save", 0, 0, &proxyscandosave);
- addcommandtotree(ps_commands, "spew", 0, 0, &proxyscandospew);
- addcommandtotree(ps_commands, "showkill", 0, 0, &proxyscandoshowkill);
- addcommandtotree(ps_commands, "scan", 0, 0, &proxyscandoscan);
- addcommandtotree(ps_commands, "addscan", 0, 0, &proxyscandoaddscan);
- addcommandtotree(ps_commands, "delscan", 0, 0, &proxyscandodelscan);
+ addcommandtotree(ps_commands, "spew", 0, 1, &proxyscandospew);
+ addcommandtotree(ps_commands, "showkill", 0, 1, &proxyscandoshowkill);
+ addcommandtotree(ps_commands, "scan", 0, 1, &proxyscandoscan);
+ addcommandtotree(ps_commands, "scanfile", 0, 1, &proxyscandoscanfile);
+ addcommandtotree(ps_commands, "addscan", 0, 1, &proxyscandoaddscan);
+ addcommandtotree(ps_commands, "delscan", 0, 1, &proxyscandodelscan);
/* Default scan types */
proxyscan_addscantype(STYPE_HTTP, 8080);
+ proxyscan_addscantype(STYPE_HTTP, 8118);
proxyscan_addscantype(STYPE_HTTP, 80);
proxyscan_addscantype(STYPE_HTTP, 6588);
proxyscan_addscantype(STYPE_HTTP, 8000);
proxyscan_addscantype(STYPE_HTTP, 808);
proxyscan_addscantype(STYPE_HTTP, 3332);
proxyscan_addscantype(STYPE_HTTP, 2282);
+
+ proxyscan_addscantype(STYPE_HTTP, 1644);
+ proxyscan_addscantype(STYPE_HTTP, 8081);
+ proxyscan_addscantype(STYPE_HTTP, 443);
+ proxyscan_addscantype(STYPE_HTTP, 1337);
+ proxyscan_addscantype(STYPE_HTTP, 8888);
+ proxyscan_addscantype(STYPE_HTTP, 8008);
+ proxyscan_addscantype(STYPE_HTTP, 6515);
+ proxyscan_addscantype(STYPE_HTTP, 27977);
+
proxyscan_addscantype(STYPE_SOCKS4, 559);
proxyscan_addscantype(STYPE_SOCKS4, 1080);
proxyscan_addscantype(STYPE_SOCKS5, 1080);
proxyscan_addscantype(STYPE_HTTP, 63809);
proxyscan_addscantype(STYPE_HTTP, 63000);
proxyscan_addscantype(STYPE_SOCKS4, 29992);
-
+ proxyscan_addscantype(STYPE_DIRECT_IRC, 6666);
+ proxyscan_addscantype(STYPE_DIRECT_IRC, 6667);
+ proxyscan_addscantype(STYPE_DIRECT_IRC, 6668);
+ proxyscan_addscantype(STYPE_DIRECT_IRC, 6669);
+ proxyscan_addscantype(STYPE_DIRECT_IRC, 6670);
+ proxyscan_addscantype(STYPE_ROUTER, 3128);
+ proxyscan_addscantype(STYPE_SOCKS5, 27977);
+
/* Schedule saves */
schedulerecurring(time(NULL)+3600,0,3600,&dumpcachehosts,NULL);
sp->totalbytesread=0;
memset(sp->readbuf, '\0', PSCAN_READBUFSIZE);
- sp->fd=createconnectsocket(irc_in_addr_v4_to_int(&((patricia_node_t *)sp->node)->prefix->sin),sp->port);
+ sp->fd=createconnectsocket(&((patricia_node_t *)sp->node)->prefix->sin,sp->port);
sp->state=SSTATE_CONNECTING;
if (sp->fd<0) {
/* Couldn't set up the socket? */
+ derefnode(iptree,sp->node);
freescan(sp);
return;
}
int i;
cachehost *chp;
foundproxy *fpp;
+ time_t now;
+ char reason[200];
scansdone++;
scansbyclass[sp->class]++;
fpp->next=chp->proxies;
chp->proxies=fpp;
}
-
- if (!chp->glineid) {
+
+ now=time(NULL);
+ /* the purpose of this lastgline stuff is to stop gline spam from one scan */
+ if (!chp->glineid || (now>=chp->lastgline+SCANTIMEOUT)) {
+ char buf[512];
+ struct irc_in_addr *ip;
+
+ chp->lastgline=now;
glinedhosts++;
- loggline(chp, sp->node);
- irc_send("%s GL * +*@%s 1800 %jd :Open Proxy, see http://www.quakenet.org/openproxies.html - ID: %d",
- mynumeric->content,IPtostr(((patricia_node_t *)sp->node)->prefix->sin),(intmax_t)getnettime(), chp->glineid);
- Error("proxyscan",ERR_DEBUG,"Found open proxy on host %s",IPtostr(((patricia_node_t *)sp->node)->prefix->sin));
+
+ loggline(chp, sp->node);
+ ip = &(((patricia_node_t *)sp->node)->prefix->sin);
+ snprintf(reason, sizeof(reason), "Open Proxy, see http://www.quakenet.org/openproxies.html - ID: %d", chp->glineid);
+ glinebyip("*", ip, 128, 1800, reason, GLINE_IGNORE_TRUST, "proxyscan");
+ Error("proxyscan",ERR_DEBUG,"Found open proxy on host %s",IPtostr(*ip));
+
+ snprintf(buf, sizeof(buf), "proxy-gline %lu %s %s %hu %s", time(NULL), IPtostr(*ip), scantostr(sp->type), sp->port, "irc.quakenet.org");
+ triggerhook(HOOK_SHADOW_SERVER, (void *)buf);
} else {
loggline(chp, sp->node); /* Update log only */
}
switch(sp->type) {
case STYPE_HTTP:
- sprintf(buf,"CONNECT %s:%d HTTP/1.0\r\n\r\n",myipstr->content,listenport);
+ sprintf(buf,"CONNECT %s:%d HTTP/1.0\r\n\r\n\r\n",myipstr->content,listenport);
if ((write(fd,buf,strlen(buf)))<strlen(buf)) {
/* We didn't write the full amount, DIE */
killsock(sp,SOUTCOME_CLOSED);
case STYPE_DIRECT:
/* Do nothing */
break;
+
+ case STYPE_DIRECT_IRC:
+ sprintf(buf,"PRIVMSG\r\n");
+ if ((write(fd,buf,strlen(buf)))<strlen(buf)) {
+ killsock(sp, SOUTCOME_CLOSED);
+ return;
+ }
+
+ /* Do nothing */
+ break;
+
+ case STYPE_ROUTER:
+ sprintf(buf,"GET /nonexistent HTTP/1.0\r\n\r\n");
+ if ((write(fd,buf,strlen(buf)))<strlen(buf)) {
+ killsock(sp, SOUTCOME_CLOSED);
+ return;
+ }
+
+ /* Do nothing */
+ break;
}
break;
sp->bytesread+=res;
sp->totalbytesread+=res;
- for (i=0;i<sp->bytesread - MAGICSTRINGLENGTH;i++) {
- if (!strncmp(sp->readbuf+i, MAGICSTRING, MAGICSTRINGLENGTH)) {
- /* Found the magic string */
- /* If the offset is 0, this means it was the first thing we got from the socket,
- * so it's an actual IRCD (sheesh). Note that when the buffer is full and moved,
- * the thing moved to offset 0 would previously have been tested as offset
- * PSCAN_READBUFSIZE/2.
- *
- * Skip this checking for STYPE_DIRECT scans, which are used to detect trojans setting
- * up portforwards (which will therefore show up as ircds, we rely on the port being
- * strange enough to avoid false positives */
- if (i==0 && (sp->type != STYPE_DIRECT)) {
- killsock(sp, SOUTCOME_CLOSED);
- return;
+
+ {
+ char *magicstring;
+ int magicstringlength;
+
+ if(sp->type == STYPE_DIRECT_IRC) {
+ magicstring = MAGICIRCSTRING;
+ magicstringlength = MAGICIRCSTRINGLENGTH;
+ } else if(sp->type == STYPE_ROUTER) {
+ magicstring = MAGICROUTERSTRING;
+ magicstringlength = MAGICROUTERSTRINGLENGTH;
+ } else {
+ magicstring = MAGICSTRING;
+ magicstringlength = MAGICSTRINGLENGTH;
+ if(sp->totalbytesread - res == 0) {
+ buf[0] = '\n';
+ write(fd,buf,1);
}
+ }
+
+ for (i=0;i<sp->bytesread - magicstringlength;i++) {
+ if (!strncmp(sp->readbuf+i, magicstring, magicstringlength)) {
+ /* Found the magic string */
+ /* If the offset is 0, this means it was the first thing we got from the socket,
+ * so it's an actual IRCD (sheesh). Note that when the buffer is full and moved,
+ * the thing moved to offset 0 would previously have been tested as offset
+ * PSCAN_READBUFSIZE/2.
+ *
+ * Skip this checking for STYPE_DIRECT scans, which are used to detect trojans setting
+ * up portforwards (which will therefore show up as ircds, we rely on the port being
+ * strange enough to avoid false positives */
+ if (i==0 && (sp->type != STYPE_DIRECT)) {
+ killsock(sp, SOUTCOME_CLOSED);
+ return;
+ }
- killsock(sp, SOUTCOME_OPEN);
- return;
+ killsock(sp, SOUTCOME_OPEN);
+ return;
+ }
}
}
int proxyscandospew(void *sender, int cargc, char **cargv) {
nick *np = (nick *)sender;
+ if(cargc < 1)
+ return CMD_USAGE;
+
/* check our database for the ip supplied */
unsigned long a,b,c,d;
if (4 != sscanf(cargv[0],"%lu.%lu.%lu.%lu",&a,&b,&c,&d)) {
int proxyscandoshowkill(void *sender, int cargc, char **cargv) {
nick *np = (nick *)sender;
+ if(cargc < 1)
+ return CMD_USAGE;
+
/* check our database for the id supplied */
unsigned long a;
if (1 != sscanf(cargv[0],"%lu",&a)) {
return CMD_OK;
}
+void startnickscan(nick *np) {
+ time_t t = time(NULL);
+ int i;
+ for(i=0;i<numscans;i++) {
+ /* @@@TODO: we allow a forced scan to scan the same IP multiple times atm */
+ queuescan(np->ipnode,thescans[i].type,thescans[i].port,SCLASS_NORMAL,t);
+ }
+}
+
int proxyscandoscan(void *sender, int cargc, char **cargv) {
nick *np = (nick *)sender;
patricia_node_t *node;
unsigned char bits;
int i;
+ if(cargc < 1)
+ return CMD_USAGE;
+
if (0 == ipmask_parse(cargv[0],&sin, &bits)) {
sendnoticetouser(proxyscannick,np,"Usage: scan <ip>");
} else {
sendnoticetouser(proxyscannick,np,"You may only scan single IPv4 IP's");
return CMD_OK;
}
+ if (bits != 128 || irc_in_addr_is_loopback(&sin)) {
+ sendnoticetouser(proxyscannick,np,"You may only scan single IP's");
+ return CMD_OK;
+ }
+
+ time_t t;
sendnoticetouser(proxyscannick,np,"Forcing scan of %s",IPtostr(sin));
// * Just queue the scans directly here.. plonk them on the priority queue * /
node = refnode(iptree, &sin, bits); /* node leaks node here - should only allow to scan a nick? */
+ t = time(NULL);
for(i=0;i<numscans;i++) {
/* @@@TODO: we allow a forced scan to scan the same IP multiple times atm */
- queuescan(node,thescans[i].type,thescans[i].port,SCLASS_NORMAL,time(NULL));
+ queuescan(node,thescans[i].type,thescans[i].port,SCLASS_NORMAL,t);
}
}
return CMD_OK;
}
+int proxyscandoscanfile(void *sender, int cargc, char **cargv) {
+ nick *np = (nick *)sender;
+ int i;
+ time_t t = time(NULL);
+ int pscantypes[PSCAN_MAXSCANS];
+ int maxtypes;
+ FILE *fp;
+ int count;
+
+ if ((fp=fopen("data/doscan.txt","r"))==NULL) {
+ sendnoticetouser(proxyscannick,np,"Unable to open file for reading!");
+ return CMD_ERROR;
+ }
+
+ {
+ int *tscantypes;
+ int maxno = -1;
+
+ for(i=0;i<numscans;i++)
+ if(thescans[i].type > maxno)
+ maxno = thescans[i].type;
+
+ tscantypes = malloc(sizeof(int) * maxno);
+ for(i=0;i<maxno;i++)
+ tscantypes[i] = 0;
+
+ for(i=0;i<numscans;i++)
+ tscantypes[thescans[i].type] = 1;
+
+ for(i=0,maxtypes=0;i<maxno;i++)
+ if(tscantypes[i])
+ pscantypes[maxtypes++] = i;
+
+ free(tscantypes);
+ }
+
+ count = 0;
+ while (!feof(fp)) {
+ patricia_node_t *node;
+ struct irc_in_addr sin;
+ unsigned char bits;
+ unsigned short port;
+ char buf[512], ip[512];
+ int res;
+
+ fgets(buf,512,fp);
+ if (feof(fp)) {
+ break;
+ }
+
+ res=sscanf(buf,"%s %hu",ip,&port);
+
+ if (res<2)
+ continue;
+
+ if (0 == ipmask_parse(ip,&sin, &bits)) {
+ /* invalid mask */
+ } else {
+ node = refnode(iptree, &sin, bits); /* LEAKS */
+ if( node ) {
+ for(i=0;i<maxtypes;i++) {
+ queuescan(node,pscantypes[i],port,SCLASS_NORMAL,t);
+ count++;
+ }
+ }
+ }
+ }
+
+ fclose(fp);
+
+ sendnoticetouser(proxyscannick,np,"Started %d scans...", count);
+ return CMD_OK;
+}
+
int proxyscandoaddscan(void *sender, int cargc, char **cargv) {
nick *np = (nick *)sender;
+ if(cargc < 1)
+ return CMD_USAGE;
+
unsigned int a,b;
if (sscanf(cargv[0],"%u %u",&a,&b) != 2) {
sendnoticetouser(proxyscannick,np,"Usage: addscan <type> <port>");
int proxyscandodelscan(void *sender, int cargc, char **cargv) {
nick *np = (nick *)sender;
+ if(cargc < 1)
+ return CMD_USAGE;
+
unsigned int a,b;
if (sscanf(cargv[0],"%u %u",&a,&b) != 2) {
sendnoticetouser(proxyscannick,np,"Usage: delscan <type> <port>");