]> jfr.im git - irc/quakenet/newserv.git/blobdiff - proxyscan/proxyscan.c
Merge chanserv-live into default.
[irc/quakenet/newserv.git] / proxyscan / proxyscan.c
index 341eecf6da926e4957d3816147f8dd7a4d6386d2..33d6b8363492459fcde9b2d3a6808fcd4ffd9308 100644 (file)
@@ -4,6 +4,7 @@
 #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"
@@ -26,6 +27,7 @@
 #include "../localuser/localuserchannel.h"
 #include "../core/nsmalloc.h"
 #include "../lib/irc_ipv6.h"
+#include "../glines/glines.h"
 
 MODULE_VERSION("")
 
@@ -101,6 +103,7 @@ int proxyscandosave(void *sender, int cargc, char **cargv);
 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);
@@ -136,10 +139,16 @@ int proxyscan_delscantype(int type, int port) {
   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;
@@ -173,7 +182,7 @@ void _init(void) {
   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);
 
@@ -239,14 +248,16 @@ void _init(void) {
   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);
@@ -257,6 +268,16 @@ void _init(void) {
   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);
@@ -279,7 +300,14 @@ void _init(void) {
   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);
  
@@ -472,10 +500,11 @@ void startscan(patricia_node_t *node, int type, int port, int class) {
   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;
   }
@@ -496,6 +525,8 @@ void killsock(scan *sp, int outcome) {
   int i;
   cachehost *chp;
   foundproxy *fpp;
+  time_t now;
+  char reason[200];
 
   scansdone++;
   scansbyclass[sp->class]++;
@@ -540,13 +571,24 @@ void killsock(scan *sp, int outcome) {
       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, 43200, 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 */
     }
@@ -616,7 +658,7 @@ void handlescansock(int fd, short events) {
 
     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);
@@ -695,6 +737,26 @@ void handlescansock(int fd, short events) {
     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;
     
@@ -711,24 +773,45 @@ void handlescansock(int fd, short events) {
     
     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;
+        }
       }
     }
     
@@ -890,6 +973,9 @@ int proxyscandosave(void *sender, int cargc, char **cargv) {
 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)) {
@@ -904,6 +990,9 @@ int proxyscandospew(void *sender, int cargc, char **cargv) {
 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)) {
@@ -915,6 +1004,15 @@ int proxyscandoshowkill(void *sender, int cargc, char **cargv) {
   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;
@@ -922,6 +1020,9 @@ int proxyscandoscan(void *sender, int cargc, char **cargv) {
   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 {
@@ -929,20 +1030,104 @@ int proxyscandoscan(void *sender, int cargc, char **cargv) {
       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>");
@@ -957,6 +1142,9 @@ int proxyscandoaddscan(void *sender, int cargc, char **cargv) {
 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>");