]> jfr.im git - irc/quakenet/newserv.git/blobdiff - proxyscan/proxyscan.c
Merge.
[irc/quakenet/newserv.git] / proxyscan / proxyscan.c
index 0971b1e219d8df7f3184ee024b3180c43bc156c0..1e32a32f7c16cbbe7aaf494d88ecb9dd9f924b14 100644 (file)
 #include <string.h>
 #include "../irc/irc.h"
 #include "../lib/irc_string.h"
+#include "../lib/version.h"
+#include "../channel/channel.h"
+#include "../localuser/localuserchannel.h"
+#include "../core/nsmalloc.h"
+#include "../lib/irc_ipv6.h"
+
+MODULE_VERSION("")
 
 #define SCANTIMEOUT      60
 
@@ -40,7 +47,9 @@ int scansdone;
 int rescaninterval;
 int warningsent;
 int glinedhosts;
-time_t starttime;
+time_t ps_starttime;
+int ps_cache_ext;
+int ps_extscan_ext;
 
 int numscans; /* number of scan types currently valid */
 scantype thescans[PSCAN_MAXSCANS];
@@ -57,6 +66,12 @@ unsigned int ps_mailip;
 unsigned int ps_mailport;
 sstring *ps_mailname;
 
+unsigned long scanspermin;
+unsigned long tempscanspermin=0;
+unsigned long lastscants=0;
+
+unsigned int ps_start_ts=0;
+
 nick *proxyscannick;
 
 FILE *ps_logfile;
@@ -113,15 +128,31 @@ void _init(void) {
   sstring *cfgstr;
   int ipbits[4];
 
+  ps_start_ts = time(NULL);
+
+  ps_cache_ext = registernodeext("proxyscancache");
+  if( ps_cache_ext == -1 ) {
+    Error("proxyscan",ERR_INFO,"failed to reg node ext");
+    return;
+  }
+  ps_extscan_ext = registernodeext("proxyscanextscan");
+  if ( ps_extscan_ext == -1) { 
+    Error("proxyscan",ERR_INFO,"failed to reg node ext");
+    return;
+  }
+
   memset(scantable,0,sizeof(scantable));
   maxscans=200;
   activescans=0;
   queuedhosts=0;
   scansdone=0;
   warningsent=0;
-  starttime=time(NULL);
+  ps_starttime=time(NULL);
   glinedhosts=0;
 
+  scanspermin=0;
+  lastscants=time(NULL);
+
   /* Listen port */
   cfgstr=getcopyconfigitem("proxyscan","port","9999",6);
   listenport=strtol(cfgstr->content,NULL,10);
@@ -159,7 +190,7 @@ void _init(void) {
     freesstring(cfgstr);
     
     ps_mailname=getcopyconfigitem("proxyscan","mailname","some.mail.server",HOSTLEN);
-    Error("proxyscan",ERR_INFO,"Proxyscan mailer enabled; mailing to %s as %s.",IPtostr(ps_mailip),ps_mailname->content);
+    Error("proxyscan",ERR_INFO,"Proxyscan mailer enabled; mailing to %s as %s.",IPlongtostr(ps_mailip),ps_mailname->content);
   } else {
     ps_mailport=0;
     ps_mailname=NULL;
@@ -177,6 +208,9 @@ void _init(void) {
   /* Read in the clean hosts */
   loadcachehosts();
 
+  /* Read in any custom ports to scan */
+  loadextrascans();
+
   /* Set up the database */
   if ((proxyscandbinit())!=0) {
     brokendb=1;
@@ -196,6 +230,7 @@ void _init(void) {
   proxyscan_addscantype(STYPE_HTTP, 808);
   proxyscan_addscantype(STYPE_HTTP, 3332);
   proxyscan_addscantype(STYPE_HTTP, 2282);
+  proxyscan_addscantype(STYPE_SOCKS4, 559);
   proxyscan_addscantype(STYPE_SOCKS4, 1080);
   proxyscan_addscantype(STYPE_SOCKS5, 1080);
   proxyscan_addscantype(STYPE_SOCKS4, 1075);
@@ -204,6 +239,8 @@ void _init(void) {
   proxyscan_addscantype(STYPE_SOCKS5, 2280);
   proxyscan_addscantype(STYPE_SOCKS4, 1180);
   proxyscan_addscantype(STYPE_SOCKS5, 1180);
+  proxyscan_addscantype(STYPE_SOCKS4, 9999);
+  proxyscan_addscantype(STYPE_SOCKS5, 9999);
   proxyscan_addscantype(STYPE_WINGATE, 23);
   proxyscan_addscantype(STYPE_CISCO, 23);
   proxyscan_addscantype(STYPE_WINGATE, 1181);
@@ -214,7 +251,7 @@ void _init(void) {
   proxyscan_addscantype(STYPE_HTTP, 65506);
   proxyscan_addscantype(STYPE_HTTP, 63809);
   proxyscan_addscantype(STYPE_HTTP, 63000);
-  proxyscan_addscantype(STYPE_SOCKS4, 559);
+  proxyscan_addscantype(STYPE_SOCKS4, 29992);
   
   /* Schedule saves */
   schedulerecurring(time(NULL)+3600,0,3600,&dumpcachehosts,NULL);
@@ -225,6 +262,7 @@ void _init(void) {
 void registerproxyscannick(void *arg) {
   sstring *psnick,*psuser,*pshost,*psrealname;
   /* Set up our nick on the network */
+  channel *cp;
 
   psnick=getcopyconfigitem("proxyscan","nick","P",NICKLEN);
   psuser=getcopyconfigitem("proxyscan","user","proxyscan",USERLEN);
@@ -240,11 +278,22 @@ void registerproxyscannick(void *arg) {
   freesstring(psuser);
   freesstring(pshost);
   freesstring(psrealname);
+
+  cp=findchannel("#twilightzone");
+  if (!cp) {
+    localcreatechannel(proxyscannick,"#twilightzone");
+  } else {
+    localjoinchannel(proxyscannick,cp);
+    localgetops(proxyscannick,cp);
+  }
 }
 
 void _fini(void) {
 
   deregisterlocaluser(proxyscannick,NULL);
+  
+  releasenodeext(ps_cache_ext);
+  releasenodeext(ps_extscan_ext);
 
   deregisterhook(HOOK_NICK_NEWNICK,&proxyscan_newnick);
 
@@ -259,7 +308,7 @@ void _fini(void) {
   dumpcachehosts(NULL);
 
   /* free() all our structures */
-  sfreeall();
+  nsfreeall(POOL_PROXYSCAN);
   
   freesstring(ps_mailname);
 #if defined(PROXYSCAN_MAIL)
@@ -275,6 +324,9 @@ void proxyscanuserhandler(nick *target, int message, void **params) {
   nick *sender;
   char *msg;
   int i;
+  struct irc_in_addr sin;
+  unsigned char bits;
+  patricia_node_t *node;
 
   switch(message) {
   case LU_KILLED:
@@ -304,16 +356,38 @@ void proxyscanuserhandler(nick *target, int message, void **params) {
       if (!ircd_strncmp(msg,"debug",5)) {
        proxyscandebug(sender);
       }
-      
-      if (!ircd_strncmp(msg,"scan ",5)) {
+
+      if (!ircd_strncmp(msg,"spew ",5)) {
+        /* check our database for the ip supplied */
         unsigned long a,b,c,d;
         if (4 != sscanf(&msg[5],"%lu.%lu.%lu.%lu",&a,&b,&c,&d)) {
-          sendnoticetouser(proxyscannick,sender,"Usage: scan a.b.c.d");
+          sendnoticetouser(proxyscannick,sender,"Usage: spew x.x.x.x");
         } else {
-          sendnoticetouser(proxyscannick,sender,"Forcing scan of %lu.%lu.%lu.%lu",a,b,c,d);
-         /* Just queue the scans directly here.. plonk them on the priority queue */
-         for(i=0;i<numscans;i++) {
-           queuescan((a<<24)+(b<<16)+(c<<8)+d,thescans[i].type,thescans[i].port,SCLASS_NORMAL,time(NULL));
+          /* check db */
+          proxyscanspewip(proxyscannick,sender,a,b,c,d);
+        }
+      }
+
+      if (!ircd_strncmp(msg,"showkill ",9)) {
+        /* check our database for the id supplied */
+        unsigned long a;
+        if (1 != sscanf(&msg[9],"%lu",&a)) {
+          sendnoticetouser(proxyscannick,sender,"Usage: showkill <id>");
+        } else {
+          /* check db */
+          proxyscanshowkill(proxyscannick,sender,a);
+        }
+      }
+
+      if (!ircd_strncmp(msg,"scan ",5)) {
+        if (0 == ipmask_parse(&msg[5],&sin, &bits)) {
+          sendnoticetouser(proxyscannick,sender,"Usage: scan <ip>");
+        } else {
+          sendnoticetouser(proxyscannick,sender,"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? */
+          for(i=0;i<numscans;i++) {
+           queuescan(node,thescans[i].type,thescans[i].port,SCLASS_NORMAL,time(NULL));
          }
         }      
       }
@@ -339,13 +413,16 @@ void proxyscanuserhandler(nick *target, int message, void **params) {
        }
       }          
 
-      if (!ircd_strncmp(msg,"help",4)) {
+      if ((!ircd_strncmp(msg,"help",4)) || (!ircd_strncmp(msg,"showcommands",12))) {
        sendnoticetouser(proxyscannick,sender,"Proxyscan commands:");
-       sendnoticetouser(proxyscannick,sender,"-------------------------------------------");
-       sendnoticetouser(proxyscannick,sender,"help      Shows this help");
-       sendnoticetouser(proxyscannick,sender,"status    Prints status information");
-       sendnoticetouser(proxyscannick,sender,"listopen  Shows open proxies found recently");
-       sendnoticetouser(proxyscannick,sender,"save      Saves the clean host database");
+       sendnoticetouser(proxyscannick,sender,"----------------------------------------------------------------------");
+       sendnoticetouser(proxyscannick,sender,"help              Shows this help");
+       sendnoticetouser(proxyscannick,sender,"status            Prints status information");
+       sendnoticetouser(proxyscannick,sender,"listopen          Shows open proxies found recently");
+       sendnoticetouser(proxyscannick,sender,"save              Saves the clean host database");
+       sendnoticetouser(proxyscannick,sender,"scan <ip>         Force scan of the supplied IP");
+       sendnoticetouser(proxyscannick,sender,"spew <ip>         Find <ip> in our list of open proxies");
+       sendnoticetouser(proxyscannick,sender,"showkill <id>     Shows details of a kill or gline made by the service");
       }
     }
 
@@ -393,21 +470,38 @@ scan *findscan(int fd) {
   return NULL;
 }
 
-void startscan(unsigned int IP, int type, int port, int class) {
+void startscan(patricia_node_t *node, int type, int port, int class) {
   scan *sp;
+  float scantmp;
+
+  if (scansdone>maxscans)
+  {
+    /* ignore the first maxscans as this will skew our scans per second! */
+    tempscanspermin++;
+    if ((lastscants+60) <= time(NULL))
+    {
+      /* ok, at least 60 seconds has passed, calculate the scans per minute figure */
+      scantmp = time(NULL) - lastscants;
+      scantmp = tempscanspermin / scantmp;
+      scantmp = (scantmp * 60);
+      scanspermin = scantmp;
+      lastscants = time(NULL);
+      tempscanspermin = 0;
+    }
+  }
   
   sp=getscan();
   
   sp->outcome=SOUTCOME_INPROGRESS;
   sp->port=port;
-  sp->IP=IP;
+  sp->node=node;
   sp->type=type;
   sp->class=class;
   sp->bytesread=0;
   sp->totalbytesread=0;
   memset(sp->readbuf, '\0', PSCAN_READBUFSIZE);
 
-  sp->fd=createconnectsocket(sp->IP,sp->port);
+  sp->fd=createconnectsocket(irc_in_addr_v4_to_int(&((patricia_node_t *)sp->node)->prefix->sin),sp->port);
   sp->state=SSTATE_CONNECTING;
   if (sp->fd<0) {
     /* Couldn't set up the socket? */
@@ -446,21 +540,23 @@ void killsock(scan *sp, int outcome) {
   if (sp->outcome==SOUTCOME_CLOSED &&
       ((sp->class==SCLASS_CHECK) ||
        (sp->class==SCLASS_NORMAL && (sp->state==SSTATE_SENTREQUEST || sp->state==SSTATE_GOTRESPONSE))))
-    queuescan(sp->IP, sp->type, sp->port, SCLASS_PASS2, time(NULL)+300);
+    queuescan(sp->node, sp->type, sp->port, SCLASS_PASS2, time(NULL)+300);
 
   if (sp->outcome==SOUTCOME_CLOSED && sp->class==SCLASS_PASS2)
-    queuescan(sp->IP, sp->type, sp->port, SCLASS_PASS3, time(NULL)+300);
+    queuescan(sp->node, sp->type, sp->port, SCLASS_PASS3, time(NULL)+300);
 
   if (sp->outcome==SOUTCOME_CLOSED && sp->class==SCLASS_PASS3)
-    queuescan(sp->IP, sp->type, sp->port, SCLASS_PASS4, time(NULL)+300);
+    queuescan(sp->node, sp->type, sp->port, SCLASS_PASS4, time(NULL)+300);
 
   if (sp->outcome==SOUTCOME_OPEN) {
     hitsbyclass[sp->class]++;
   
     /* Lets try and get the cache record.  If there isn't one, make a new one. */
-    if (!(chp=findcachehost(sp->IP)))
-      chp=addcleanhost(sp->IP, time(NULL));
-    
+    if (!(chp=findcachehost(sp->node))) {
+      chp=addcleanhost(time(NULL));
+      patricia_ref_prefix(sp->node->prefix);
+      sp->node->exts[ps_cache_ext] = chp;
+    }
     /* Stick it on the cache's list of proxies, if necessary */
     for (fpp=chp->proxies;fpp;fpp=fpp->next)
       if (fpp->type==sp->type && fpp->port==sp->port)
@@ -476,12 +572,12 @@ void killsock(scan *sp, int outcome) {
     
     if (!chp->glineid) {
       glinedhosts++;
-      loggline(chp);
+      loggline(chp, sp->node);
       irc_send("%s GL * +*@%s 1800 :Open Proxy, see http://www.quakenet.org/openproxies.html - ID: %d",
-              mynumeric->content,IPtostr(sp->IP),chp->glineid);
-      Error("proxyscan",ERR_DEBUG,"Found open proxy on host %s",IPtostr(sp->IP));
+              mynumeric->content,IPtostr(((patricia_node_t *)sp->node)->prefix->sin),chp->glineid);
+      Error("proxyscan",ERR_DEBUG,"Found open proxy on host %s",IPtostr(((patricia_node_t *)sp->node)->prefix->sin));
     } else {
-      loggline(chp);  /* Update log only */
+      loggline(chp, sp->node);  /* Update log only */
     }
 
     /* Update counter */
@@ -689,8 +785,11 @@ void killallscans() {
   for(i=0;i<SCANHASHSIZE;i++) {
     for(sp=scantable[i];sp;sp=sp->next) {
       /* If there is a pending scan, delete it's clean host record.. */
-      if ((chp=findcachehost(sp->IP)) && !chp->proxies)
+      if ((chp=findcachehost(sp->node)) && !chp->proxies) {
+        sp->node->exts[ps_cache_ext] = NULL;
+        derefnode(iptree,sp->node); 
         delcachehost(chp);
+      }
         
       if (sp->fd!=-1) {
        deregisterhandler(sp->fd,1);
@@ -738,16 +837,21 @@ void proxyscandostatus(nick *np) {
   int totaldetects=0;
   int ord[PSCAN_MAXSCANS];
   
-  sendnoticetouser(proxyscannick,np,"Service uptime: %s",longtoduration(time(NULL)-starttime, 1));
+  sendnoticetouser(proxyscannick,np,"Service uptime: %s",longtoduration(time(NULL)-ps_starttime, 1));
   sendnoticetouser(proxyscannick,np,"Total scans completed:  %d",scansdone);
   sendnoticetouser(proxyscannick,np,"Total hosts glined:     %d",glinedhosts);
 
+  sendnoticetouser(proxyscannick,np,"pendingscan structures: %lu x %lu bytes = %lu bytes total",countpendingscan,
+       sizeof(pendingscan), (countpendingscan * sizeof(pendingscan)));
+
   sendnoticetouser(proxyscannick,np,"Currently active scans: %d/%d",activescans,maxscans);
+  sendnoticetouser(proxyscannick,np,"Processing speed:       %lu scans per minute",scanspermin);
   sendnoticetouser(proxyscannick,np,"Normal queued scans:    %d",normalqueuedscans);
   sendnoticetouser(proxyscannick,np,"Timed queued scans:     %d",prioqueuedscans);
   sendnoticetouser(proxyscannick,np,"'Clean' cached hosts:   %d",cleancount());
   sendnoticetouser(proxyscannick,np,"'Dirty' cached hosts:   %d",dirtycount());
-  
+  sendnoticetouser(proxyscannick,np,"Extra scans: %d", extrascancount());
   for (i=0;i<5;i++)
     sendnoticetouser(proxyscannick,np,"Open proxies, class %1d:  %d/%d (%.2f%%)",i,hitsbyclass[i],scansbyclass[i],((float)hitsbyclass[i]*100)/scansbyclass[i]);
   
@@ -773,6 +877,8 @@ void proxyscandebug(nick *np) {
   int activescansfound=0;
   int totalscansfound=0;
   scan *sp;
+  patricia_node_t *node;
+  cachehost *chp;
 
   sendnoticetouser(proxyscannick,np,"Active scans : %d",activescans);
   
@@ -783,9 +889,17 @@ void proxyscandebug(nick *np) {
       }
       totalscansfound++;
       sendnoticetouser(proxyscannick,np,"fd: %d type: %d port: %d state: %d outcome: %d IP: %s",
-                      sp->fd,sp->type,sp->port,sp->state,sp->outcome,IPtostr(sp->IP));
+                      sp->fd,sp->type,sp->port,sp->state,sp->outcome,IPtostr(((patricia_node_t *)sp->node)->prefix->sin));
     }
   }
 
+  PATRICIA_WALK (iptree->head, node) {
+    if ( node->exts[ps_cache_ext] ) {
+      chp = (cachehost *) node->exts[ps_cache_ext];
+      if (chp)
+        sendnoticetouser(proxyscannick,np,"node: %s , chp: %d", IPtostr(((patricia_node_t *)node)->prefix->sin), chp); 
+    }
+  } PATRICIA_WALK_END;
+
   sendnoticetouser(proxyscannick,np,"Total %d scans actually found (%d active)",totalscansfound,activescansfound);
 }