]>
jfr.im git - irc/quakenet/newserv.git/blob - proxyscan/proxyscan.c
6 #include <sys/socket.h>
9 #include "../core/error.h"
10 #include "../core/events.h"
14 #include "../nick/nick.h"
15 #include "../core/hooks.h"
16 #include "../lib/sstring.h"
17 #include "../irc/irc_config.h"
18 #include "../localuser/localuser.h"
19 #include "../core/config.h"
21 #include "../core/schedule.h"
23 #include "../irc/irc.h"
24 #include "../lib/irc_string.h"
25 #include "../lib/version.h"
26 #include "../channel/channel.h"
27 #include "../localuser/localuserchannel.h"
28 #include "../core/nsmalloc.h"
29 #include "../lib/irc_ipv6.h"
30 #include "../glines/glines.h"
34 #define SCANTIMEOUT 60
36 #define SCANHOSTHASHSIZE 1000
37 #define SCANHASHSIZE 400
39 /* It's unlikely you'll get 100k of preamble before a connect... */
40 #define READ_SANITY_LIMIT 102400
42 scan
*scantable
[SCANHASHSIZE
];
44 CommandTree
*ps_commands
;
59 int numscans
; /* number of scan types currently valid */
60 scantype thescans
[PSCAN_MAXSCANS
];
62 unsigned int hitsbyclass
[10];
63 unsigned int scansbyclass
[10];
67 unsigned short listenport
;
70 unsigned int ps_mailip
;
71 unsigned int ps_mailport
;
74 unsigned long scanspermin
;
75 unsigned long tempscanspermin
=0;
76 unsigned long lastscants
=0;
78 unsigned int ps_start_ts
=0;
85 void handlescansock(int fd
, short events
);
86 void timeoutscansock(void *arg
);
87 void proxyscan_newnick(int hooknum
, void *arg
);
88 void proxyscan_lostnick(int hooknum
, void *arg
);
89 void proxyscan_onconnect(int hooknum
, void *arg
);
90 void proxyscanuserhandler(nick
*target
, int message
, void **params
);
91 void registerproxyscannick();
92 void killsock(scan
*sp
, int outcome
);
94 void proxyscanstats(int hooknum
, void *arg
);
95 void sendlagwarning();
96 void proxyscan_newip(nick
*np
, unsigned long ip
);
97 int proxyscan_addscantype(int type
, int port
);
98 int proxyscan_delscantype(int type
, int port
);
100 int proxyscandostatus(void *sender
, int cargc
, char **cargv
);
101 int proxyscandebug(void *sender
, int cargc
, char **cargv
);
102 int proxyscandosave(void *sender
, int cargc
, char **cargv
);
103 int proxyscandospew(void *sender
, int cargc
, char **cargv
);
104 int proxyscandoshowkill(void *sender
, int cargc
, char **cargv
);
105 int proxyscandoscan(void *sender
, int cargc
, char **cargv
);
106 int proxyscandoscanfile(void *sender
, int cargc
, char **cargv
);
107 int proxyscandoaddscan(void *sender
, int cargc
, char **cargv
);
108 int proxyscandodelscan(void *sender
, int cargc
, char **cargv
);
109 int proxyscandoshowcommands(void *sender
, int cargc
, char **cargv
);
111 int proxyscan_addscantype(int type
, int port
) {
112 /* Check we have a spare scan slot */
114 if (numscans
>=PSCAN_MAXSCANS
)
117 thescans
[numscans
].type
=type
;
118 thescans
[numscans
].port
=port
;
119 thescans
[numscans
].hits
=0;
126 int proxyscan_delscantype(int type
, int port
) {
129 for (i
=0;i
<numscans
;i
++)
130 if (thescans
[i
].type
==type
&& thescans
[i
].port
==port
)
136 memmove(thescans
+i
, thescans
+(i
+1), (PSCAN_MAXSCANS
-(i
+1)) * sizeof(scantype
));
142 void ignorepipe(int signal_
) {
143 signal(SIGPIPE
, ignorepipe
); /* HACK */
150 signal(SIGPIPE
, ignorepipe
); /* HACK */
152 ps_start_ts
= time(NULL
);
156 ps_cache_ext
= registernodeext("proxyscancache");
157 if( ps_cache_ext
== -1 ) {
158 Error("proxyscan",ERR_INFO
,"failed to reg node ext");
161 ps_extscan_ext
= registernodeext("proxyscanextscan");
162 if ( ps_extscan_ext
== -1) {
163 Error("proxyscan",ERR_INFO
,"failed to reg node ext");
167 memset(scantable
,0,sizeof(scantable
));
173 ps_starttime
=time(NULL
);
177 lastscants
=time(NULL
);
180 cfgstr
=getcopyconfigitem("proxyscan","port","9999",6);
181 listenport
=strtol(cfgstr
->content
,NULL
,10);
184 /* Max concurrent scans */
185 cfgstr
=getcopyconfigitem("proxyscan","maxscans","200",10);
186 maxscans
=strtol(cfgstr
->content
,NULL
,10);
189 /* Clean host timeout */
190 cfgstr
=getcopyconfigitem("proxyscan","rescaninterval","3600",7);
191 rescaninterval
=strtol(cfgstr
->content
,NULL
,10);
192 cachehostinit(rescaninterval
);
195 /* this default will NOT work well */
196 myipstr
=getcopyconfigitem("proxyscan","ip","127.0.0.1",16);
198 sscanf(myipstr
->content
,"%d.%d.%d.%d",&ipbits
[0],&ipbits
[1],&ipbits
[2],&ipbits
[3]);
200 myip
=((ipbits
[0]&0xFF)<<24)+((ipbits
[1]&0xFF)<<16)+
201 ((ipbits
[2]&0xFF)<<8)+(ipbits
[3]&0xFF);
203 #if defined(PROXYSCAN_MAIL)
205 cfgstr
=getcopyconfigitem("proxyscan","mailerip","",16);
209 sscanf(cfgstr
->content
,"%d.%d.%d.%d",&ipbits
[0],&ipbits
[1],&ipbits
[2],&ipbits
[3]);
210 ps_mailip
= ((ipbits
[0]&0xFF)<<24)+((ipbits
[1]&0xFF)<<16)+
211 ((ipbits
[2]&0xFF)<<8)+(ipbits
[3]&0xFF);
215 ps_mailname
=getcopyconfigitem("proxyscan","mailname","some.mail.server",HOSTLEN
);
216 Error("proxyscan",ERR_INFO
,"Proxyscan mailer enabled; mailing to %s as %s.",IPlongtostr(ps_mailip
),ps_mailname
->content
);
224 /* Set up our nick on the network */
225 scheduleoneshot(time(NULL
),®isterproxyscannick
,NULL
);
227 registerhook(HOOK_SERVER_END_OF_BURST
, &proxyscan_onconnect
);
229 registerhook(HOOK_NICK_NEWNICK
,&proxyscan_newnick
);
231 registerhook(HOOK_CORE_STATSREQUEST
,&proxyscanstats
);
233 /* Read in the clean hosts */
236 /* Read in any custom ports to scan */
239 /* Set up the database */
240 if ((proxyscandbinit())!=0) {
246 ps_commands
= newcommandtree();
247 addcommandtotree(ps_commands
, "showcommands", 0, 0, &proxyscandoshowcommands
);
248 addcommandtotree(ps_commands
, "status", 0, 0, &proxyscandostatus
);
249 addcommandtotree(ps_commands
, "listopen", 0, 0, &proxyscandolistopen
);
250 addcommandtotree(ps_commands
, "save", 0, 0, &proxyscandosave
);
251 addcommandtotree(ps_commands
, "spew", 0, 1, &proxyscandospew
);
252 addcommandtotree(ps_commands
, "showkill", 0, 1, &proxyscandoshowkill
);
253 addcommandtotree(ps_commands
, "scan", 0, 1, &proxyscandoscan
);
254 addcommandtotree(ps_commands
, "scanfile", 0, 1, &proxyscandoscanfile
);
255 addcommandtotree(ps_commands
, "addscan", 0, 1, &proxyscandoaddscan
);
256 addcommandtotree(ps_commands
, "delscan", 0, 1, &proxyscandodelscan
);
258 /* Default scan types */
259 proxyscan_addscantype(STYPE_HTTP
, 8080);
260 proxyscan_addscantype(STYPE_HTTP
, 8118);
261 proxyscan_addscantype(STYPE_HTTP
, 80);
262 proxyscan_addscantype(STYPE_HTTP
, 6588);
263 proxyscan_addscantype(STYPE_HTTP
, 8000);
264 proxyscan_addscantype(STYPE_HTTP
, 3128);
265 proxyscan_addscantype(STYPE_HTTP
, 3802);
266 proxyscan_addscantype(STYPE_HTTP
, 5490);
267 proxyscan_addscantype(STYPE_HTTP
, 7441);
268 proxyscan_addscantype(STYPE_HTTP
, 808);
269 proxyscan_addscantype(STYPE_HTTP
, 3332);
270 proxyscan_addscantype(STYPE_HTTP
, 2282);
272 proxyscan_addscantype(STYPE_HTTP
, 1644);
273 proxyscan_addscantype(STYPE_HTTP
, 8081);
274 proxyscan_addscantype(STYPE_HTTP
, 443);
275 proxyscan_addscantype(STYPE_HTTP
, 1337);
276 proxyscan_addscantype(STYPE_HTTP
, 8888);
277 proxyscan_addscantype(STYPE_HTTP
, 8008);
278 proxyscan_addscantype(STYPE_HTTP
, 6515);
279 proxyscan_addscantype(STYPE_HTTP
, 27977);
281 proxyscan_addscantype(STYPE_SOCKS4
, 559);
282 proxyscan_addscantype(STYPE_SOCKS4
, 1080);
283 proxyscan_addscantype(STYPE_SOCKS5
, 1080);
284 proxyscan_addscantype(STYPE_SOCKS4
, 1075);
285 proxyscan_addscantype(STYPE_SOCKS5
, 1075);
286 proxyscan_addscantype(STYPE_SOCKS4
, 2280);
287 proxyscan_addscantype(STYPE_SOCKS5
, 2280);
288 proxyscan_addscantype(STYPE_SOCKS4
, 1180);
289 proxyscan_addscantype(STYPE_SOCKS5
, 1180);
290 proxyscan_addscantype(STYPE_SOCKS4
, 9999);
291 proxyscan_addscantype(STYPE_SOCKS5
, 9999);
292 proxyscan_addscantype(STYPE_WINGATE
, 23);
293 proxyscan_addscantype(STYPE_CISCO
, 23);
294 proxyscan_addscantype(STYPE_WINGATE
, 1181);
295 proxyscan_addscantype(STYPE_SOCKS5
, 1978);
296 proxyscan_addscantype(STYPE_SOCKS5
, 1029);
297 proxyscan_addscantype(STYPE_SOCKS5
, 3801);
298 proxyscan_addscantype(STYPE_SOCKS5
, 3331);
299 proxyscan_addscantype(STYPE_HTTP
, 65506);
300 proxyscan_addscantype(STYPE_HTTP
, 63809);
301 proxyscan_addscantype(STYPE_HTTP
, 63000);
302 proxyscan_addscantype(STYPE_SOCKS4
, 29992);
303 proxyscan_addscantype(STYPE_DIRECT_IRC
, 6666);
304 proxyscan_addscantype(STYPE_DIRECT_IRC
, 6667);
305 proxyscan_addscantype(STYPE_DIRECT_IRC
, 6668);
306 proxyscan_addscantype(STYPE_DIRECT_IRC
, 6669);
307 proxyscan_addscantype(STYPE_DIRECT_IRC
, 6670);
308 proxyscan_addscantype(STYPE_ROUTER
, 3128);
309 proxyscan_addscantype(STYPE_SOCKS5
, 27977);
312 schedulerecurring(time(NULL
)+3600,0,3600,&dumpcachehosts
,NULL
);
314 ps_logfile
=fopen("logs/proxyscan.log","a");
317 /* if we're already connected, assume we're just reloading module (i.e. have a completed burst) */
323 void registerproxyscannick(void *arg
) {
324 sstring
*psnick
,*psuser
,*pshost
,*psrealname
;
325 /* Set up our nick on the network */
328 psnick
=getcopyconfigitem("proxyscan","nick","P",NICKLEN
);
329 psuser
=getcopyconfigitem("proxyscan","user","proxyscan",USERLEN
);
330 pshost
=getcopyconfigitem("proxyscan","host","some.host",HOSTLEN
);
331 psrealname
=getcopyconfigitem("proxyscan","realname","Proxyscan",REALLEN
);
333 proxyscannick
=registerlocaluser(psnick
->content
,psuser
->content
,pshost
->content
,
335 NULL
,UMODE_OPER
|UMODE_SERVICE
|UMODE_DEAF
,
336 &proxyscanuserhandler
);
341 freesstring(psrealname
);
343 cp
=findchannel("#twilightzone");
345 localcreatechannel(proxyscannick
,"#twilightzone");
347 localjoinchannel(proxyscannick
,cp
);
348 localgetops(proxyscannick
,cp
);
354 deregisterlocaluser(proxyscannick
,NULL
);
356 deregisterhook(HOOK_SERVER_END_OF_BURST
, &proxyscan_onconnect
);
358 deregisterhook(HOOK_NICK_NEWNICK
,&proxyscan_newnick
);
360 deregisterhook(HOOK_CORE_STATSREQUEST
,&proxyscanstats
);
362 deleteschedule(NULL
,&dumpcachehosts
,NULL
);
364 destroycommandtree(ps_commands
);
366 /* Kill any scans in progress */
369 /* Dump the database - AFTER killallscans() which prunes it */
370 dumpcachehosts(NULL
);
372 /* dump any cached hosts before deleting the extensions */
373 releasenodeext(ps_cache_ext
);
374 releasenodeext(ps_extscan_ext
);
376 /* free() all our structures */
377 nsfreeall(POOL_PROXYSCAN
);
379 freesstring(myipstr
);
380 freesstring(ps_mailname
);
381 #if defined(PROXYSCAN_MAIL)
382 if (psm_mailerfd
!=-1)
383 deregisterhandler(psm_mailerfd
,1);
390 void proxyscanuserhandler(nick
*target
, int message
, void **params
) {
398 scheduleoneshot(time(NULL
)+1,®isterproxyscannick
,NULL
);
404 sender
=(nick
*)params
[0];
406 if (IsOper(sender
)) {
407 cargc
= splitline((char *)params
[1], cargv
, 20, 0);
412 ps_command
= findcommandintree(ps_commands
, cargv
[0], 1);
415 sendnoticetouser(proxyscannick
,sender
, "Unknown command.");
419 if ( ps_command
->maxparams
< (cargc
-1) ) {
420 rejoinline(cargv
[ps_command
->maxparams
], cargc
- (ps_command
->maxparams
));
421 cargc
= (ps_command
->maxparams
) + 1;
424 (ps_command
->handler
)((void *)sender
, cargc
- 1, &(cargv
[1]));
433 void addscantohash(scan
*sp
) {
435 hash
=(sp
->fd
)%SCANHASHSIZE
;
437 sp
->next
=scantable
[hash
];
443 void delscanfromhash(scan
*sp
) {
447 hash
=(sp
->fd
)%SCANHASHSIZE
;
449 for (sh
=&(scantable
[hash
]);*sh
;sh
=&((*sh
)->next
)) {
459 scan
*findscan(int fd
) {
463 hash
=fd%SCANHASHSIZE
;
465 for (sp
=scantable
[hash
];sp
;sp
=sp
->next
)
472 void startscan(patricia_node_t
*node
, int type
, int port
, int class) {
476 if (scansdone
>maxscans
)
478 /* ignore the first maxscans as this will skew our scans per second! */
480 if ((lastscants
+60) <= time(NULL
))
482 /* ok, at least 60 seconds has passed, calculate the scans per minute figure */
483 scantmp
= time(NULL
) - lastscants
;
484 scantmp
= tempscanspermin
/ scantmp
;
485 scantmp
= (scantmp
* 60);
486 scanspermin
= scantmp
;
487 lastscants
= time(NULL
);
494 sp
->outcome
=SOUTCOME_INPROGRESS
;
500 sp
->totalbytesread
=0;
501 memset(sp
->readbuf
, '\0', PSCAN_READBUFSIZE
);
503 sp
->fd
=createconnectsocket(&((patricia_node_t
*)sp
->node
)->prefix
->sin
,sp
->port
);
504 sp
->state
=SSTATE_CONNECTING
;
506 /* Couldn't set up the socket? */
507 derefnode(iptree
,sp
->node
);
511 /* Wait until it is writeable */
512 registerhandler(sp
->fd
,POLLERR
|POLLHUP
|POLLOUT
,&handlescansock
);
513 /* And set a timeout */
514 sp
->sch
=scheduleoneshot(time(NULL
)+SCANTIMEOUT
,&timeoutscansock
,(void *)sp
);
518 void timeoutscansock(void *arg
) {
519 scan
*sp
=(scan
*)arg
;
521 killsock(sp
, SOUTCOME_CLOSED
);
524 void killsock(scan
*sp
, int outcome
) {
532 scansbyclass
[sp
->class]++;
534 /* Remove the socket from the schedule/event lists */
535 deregisterhandler(sp
->fd
,1); /* this will close the fd for us */
536 deleteschedule(sp
->sch
,&timeoutscansock
,(void *)sp
);
541 /* See if we need to queue another scan.. */
542 if (sp
->outcome
==SOUTCOME_CLOSED
&&
543 ((sp
->class==SCLASS_CHECK
) ||
544 (sp
->class==SCLASS_NORMAL
&& (sp
->state
==SSTATE_SENTREQUEST
|| sp
->state
==SSTATE_GOTRESPONSE
))))
545 queuescan(sp
->node
, sp
->type
, sp
->port
, SCLASS_PASS2
, time(NULL
)+300);
547 if (sp
->outcome
==SOUTCOME_CLOSED
&& sp
->class==SCLASS_PASS2
)
548 queuescan(sp
->node
, sp
->type
, sp
->port
, SCLASS_PASS3
, time(NULL
)+300);
550 if (sp
->outcome
==SOUTCOME_CLOSED
&& sp
->class==SCLASS_PASS3
)
551 queuescan(sp
->node
, sp
->type
, sp
->port
, SCLASS_PASS4
, time(NULL
)+300);
553 if (sp
->outcome
==SOUTCOME_OPEN
) {
554 hitsbyclass
[sp
->class]++;
556 /* Lets try and get the cache record. If there isn't one, make a new one. */
557 if (!(chp
=findcachehost(sp
->node
))) {
558 chp
=addcleanhost(time(NULL
));
559 patricia_ref_prefix(sp
->node
->prefix
);
560 sp
->node
->exts
[ps_cache_ext
] = chp
;
562 /* Stick it on the cache's list of proxies, if necessary */
563 for (fpp
=chp
->proxies
;fpp
;fpp
=fpp
->next
)
564 if (fpp
->type
==sp
->type
&& fpp
->port
==sp
->port
)
571 fpp
->next
=chp
->proxies
;
576 /* the purpose of this lastgline stuff is to stop gline spam from one scan */
577 if (!chp
->glineid
|| (now
>=chp
->lastgline
+SCANTIMEOUT
)) {
579 struct irc_in_addr
*ip
;
584 loggline(chp
, sp
->node
);
585 ip
= &(((patricia_node_t
*)sp
->node
)->prefix
->sin
);
586 snprintf(reason
, sizeof(reason
), "Open Proxy, see http://www.quakenet.org/openproxies.html - ID: %d", chp
->glineid
);
587 glinebyip("*", ip
, 128, 1800, reason
, GLINE_IGNORE_TRUST
, "proxyscan");
588 Error("proxyscan",ERR_DEBUG
,"Found open proxy on host %s",IPtostr(*ip
));
590 snprintf(buf
, sizeof(buf
), "proxy-gline %lu %s %s %hu %s", time(NULL
), IPtostr(*ip
), scantostr(sp
->type
), sp
->port
, "irc.quakenet.org");
591 triggerhook(HOOK_SHADOW_SERVER
, (void *)buf
);
593 loggline(chp
, sp
->node
); /* Update log only */
597 for(i
=0;i
<numscans
;i
++) {
598 if (thescans
[i
].type
==sp
->type
&& thescans
[i
].port
==sp
->port
) {
605 /* deref prefix (referenced in queuescan) */
606 derefnode(iptree
,sp
->node
);
609 /* kick the queue.. */
613 void handlescansock(int fd
, short events
) {
619 unsigned short netport
;
621 if ((sp
=findscan(fd
))==NULL
) {
622 /* Not found; return and hope it goes away */
623 Error("proxyscan",ERR_ERROR
,"Unexpected message from fd %d",fd
);
627 /* It woke up, delete the alarm call.. */
628 deleteschedule(sp
->sch
,&timeoutscansock
,(void *)sp
);
630 if (events
& (POLLERR
|POLLHUP
)) {
631 /* Some kind of error; give up on this socket */
632 if (sp
->state
==SSTATE_GOTRESPONSE
) {
633 /* If the error occured while we were waiting for a response, we might have
634 * received the "OPEN PROXY!" message and the EOF at the same time, so continue
636 /* Error("proxyscan",ERR_DEBUG,"Got error in GOTRESPONSE state for %s, continuing.",IPtostr(sp->host->IP)); */
638 killsock(sp
, SOUTCOME_CLOSED
);
643 /* Otherwise, we got what we wanted.. */
646 case SSTATE_CONNECTING
:
647 /* OK, we got activity while connecting, so we're going to send some
648 * request depending on scan type. However, we can reregister everything
649 * here to save duplicate code: This code is common for all handlers */
651 /* Delete the old handler */
652 deregisterhandler(fd
,0);
653 /* Set the new one */
654 registerhandler(fd
,POLLERR
|POLLHUP
|POLLIN
,&handlescansock
);
655 sp
->sch
=scheduleoneshot(time(NULL
)+SCANTIMEOUT
,&timeoutscansock
,(void *)sp
);
657 sp
->state
=SSTATE_SENTREQUEST
;
661 sprintf(buf
,"CONNECT %s:%d HTTP/1.0\r\n\r\n\r\n",myipstr
->content
,listenport
);
662 if ((write(fd
,buf
,strlen(buf
)))<strlen(buf
)) {
663 /* We didn't write the full amount, DIE */
664 killsock(sp
,SOUTCOME_CLOSED
);
670 /* set up the buffer */
672 netport
=htons(listenport
);
673 memcpy(&buf
[4],&netip
,4);
674 memcpy(&buf
[2],&netport
,2);
678 if ((write(fd
,buf
,9))<9) {
679 /* Didn't write enough, give up */
680 killsock(sp
,SOUTCOME_CLOSED
);
686 /* Set up initial request buffer */
690 if ((write(fd
,buf
,3))>3) {
691 /* Didn't write enough, give up */
692 killsock(sp
,SOUTCOME_CLOSED
);
696 /* Now the actual connect request */
702 netport
=htons(listenport
);
703 memcpy(&buf
[4],&netip
,4);
704 memcpy(&buf
[8],&netport
,2);
705 res
=write(fd
,buf
,10);
707 killsock(sp
,SOUTCOME_CLOSED
);
713 /* Send wingate request */
714 sprintf(buf
,"%s:%d\r\n",myipstr
->content
,listenport
);
715 if((write(fd
,buf
,strlen(buf
)))<strlen(buf
)) {
716 killsock(sp
,SOUTCOME_CLOSED
);
722 /* Send cisco request */
723 sprintf(buf
,"cisco\r\n");
724 if ((write(fd
,buf
,strlen(buf
)))<strlen(buf
)) {
725 killsock(sp
, SOUTCOME_CLOSED
);
729 sprintf(buf
,"telnet %s %d\r\n",myipstr
->content
,listenport
);
730 if ((write(fd
,buf
,strlen(buf
)))<strlen(buf
)) {
731 killsock(sp
, SOUTCOME_CLOSED
);
741 case STYPE_DIRECT_IRC
:
742 sprintf(buf
,"PRIVMSG\r\n");
743 if ((write(fd
,buf
,strlen(buf
)))<strlen(buf
)) {
744 killsock(sp
, SOUTCOME_CLOSED
);
752 sprintf(buf
,"GET /nonexistent HTTP/1.0\r\n\r\n");
753 if ((write(fd
,buf
,strlen(buf
)))<strlen(buf
)) {
754 killsock(sp
, SOUTCOME_CLOSED
);
763 case SSTATE_SENTREQUEST
:
764 res
=read(fd
, sp
->readbuf
+sp
->bytesread
, PSCAN_READBUFSIZE
-sp
->bytesread
);
767 if ((errno
!=EINTR
&& errno
!=EWOULDBLOCK
) || res
==0) {
769 killsock(sp
, SOUTCOME_CLOSED
);
775 sp
->totalbytesread
+=res
;
779 int magicstringlength
;
781 if(sp
->type
== STYPE_DIRECT_IRC
) {
782 magicstring
= MAGICIRCSTRING
;
783 magicstringlength
= MAGICIRCSTRINGLENGTH
;
784 } else if(sp
->type
== STYPE_ROUTER
) {
785 magicstring
= MAGICROUTERSTRING
;
786 magicstringlength
= MAGICROUTERSTRINGLENGTH
;
788 magicstring
= MAGICSTRING
;
789 magicstringlength
= MAGICSTRINGLENGTH
;
790 if(sp
->totalbytesread
- res
== 0) {
796 for (i
=0;i
<sp
->bytesread
- magicstringlength
;i
++) {
797 if (!strncmp(sp
->readbuf
+i
, magicstring
, magicstringlength
)) {
798 /* Found the magic string */
799 /* If the offset is 0, this means it was the first thing we got from the socket,
800 * so it's an actual IRCD (sheesh). Note that when the buffer is full and moved,
801 * the thing moved to offset 0 would previously have been tested as offset
802 * PSCAN_READBUFSIZE/2.
804 * Skip this checking for STYPE_DIRECT scans, which are used to detect trojans setting
805 * up portforwards (which will therefore show up as ircds, we rely on the port being
806 * strange enough to avoid false positives */
807 if (i
==0 && (sp
->type
!= STYPE_DIRECT
)) {
808 killsock(sp
, SOUTCOME_CLOSED
);
812 killsock(sp
, SOUTCOME_OPEN
);
818 /* If the buffer is full, move half of it along to make room */
819 if (sp
->bytesread
== PSCAN_READBUFSIZE
) {
820 memcpy(sp
->readbuf
, sp
->readbuf
+ (PSCAN_READBUFSIZE
)/2, PSCAN_READBUFSIZE
/2);
821 sp
->bytesread
= PSCAN_READBUFSIZE
/2;
824 /* Don't read data forever.. */
825 if (sp
->totalbytesread
> READ_SANITY_LIMIT
) {
826 killsock(sp
, SOUTCOME_CLOSED
);
830 /* No magic string yet, we schedule another timeout in case it comes later. */
831 sp
->sch
=scheduleoneshot(time(NULL
)+SCANTIMEOUT
,&timeoutscansock
,(void *)sp
);
836 void killallscans() {
841 for(i
=0;i
<SCANHASHSIZE
;i
++) {
842 for(sp
=scantable
[i
];sp
;sp
=sp
->next
) {
843 /* If there is a pending scan, delete it's clean host record.. */
844 if ((chp
=findcachehost(sp
->node
)) && !chp
->proxies
) {
845 sp
->node
->exts
[ps_cache_ext
] = NULL
;
846 derefnode(iptree
,sp
->node
);
851 deregisterhandler(sp
->fd
,1);
852 deleteschedule(sp
->sch
,&timeoutscansock
,(void *)(sp
));
858 void proxyscanstats(int hooknum
, void *arg
) {
861 sprintf(buf
, "Proxyscn: %6d/%4d scans complete/in progress. %d hosts queued.",
862 scansdone
,activescans
,queuedhosts
);
863 triggerhook(HOOK_CORE_STATSREPLY
,buf
);
864 sprintf(buf
, "Proxyscn: %6u known clean hosts",cleancount());
865 triggerhook(HOOK_CORE_STATSREPLY
,buf
);
868 void sendlagwarning() {
872 for (i
=0;i
<MAXSERVERS
;i
++) {
873 if (serverlist
[i
].maxusernum
>0) {
874 for(j
=0;j
<serverlist
[i
].maxusernum
;j
++) {
875 np
=servernicks
[i
][j
];
876 if (np
!=NULL
&& IsOper(np
)) {
877 sendnoticetouser(proxyscannick
,np
,"Warning: More than 20,000 hosts to scan - I'm lagging behind badly!");
884 int pscansort(const void *a
, const void *b
) {
885 int ra
= *((const int *)a
);
886 int rb
= *((const int *)b
);
888 return thescans
[ra
].hits
- thescans
[rb
].hits
;
891 int proxyscandostatus(void *sender
, int cargc
, char **cargv
) {
892 nick
*np
= (nick
*) sender
;
895 int ord
[PSCAN_MAXSCANS
];
897 sendnoticetouser(proxyscannick
,np
,"Service uptime: %s",longtoduration(time(NULL
)-ps_starttime
, 1));
898 sendnoticetouser(proxyscannick
,np
,"Total scans completed: %d",scansdone
);
899 sendnoticetouser(proxyscannick
,np
,"Total hosts glined: %d",glinedhosts
);
901 sendnoticetouser(proxyscannick
,np
,"pendingscan structures: %lu x %lu bytes = %lu bytes total",countpendingscan
,
902 sizeof(pendingscan
), (countpendingscan
* sizeof(pendingscan
)));
904 sendnoticetouser(proxyscannick
,np
,"Currently active scans: %d/%d",activescans
,maxscans
);
905 sendnoticetouser(proxyscannick
,np
,"Processing speed: %lu scans per minute",scanspermin
);
906 sendnoticetouser(proxyscannick
,np
,"Normal queued scans: %d",normalqueuedscans
);
907 sendnoticetouser(proxyscannick
,np
,"Timed queued scans: %d",prioqueuedscans
);
908 sendnoticetouser(proxyscannick
,np
,"'Clean' cached hosts: %d",cleancount());
909 sendnoticetouser(proxyscannick
,np
,"'Dirty' cached hosts: %d",dirtycount());
911 sendnoticetouser(proxyscannick
,np
,"Extra scans: %d", extrascancount());
913 sendnoticetouser(proxyscannick
,np
,"Open proxies, class %1d: %d/%d (%.2f%%)",i
,hitsbyclass
[i
],scansbyclass
[i
],((float)hitsbyclass
[i
]*100)/scansbyclass
[i
]);
915 for (i
=0;i
<numscans
;i
++)
916 totaldetects
+=thescans
[i
].hits
;
918 for (i
=0;i
<numscans
;i
++)
921 qsort(ord
,numscans
,sizeof(int),pscansort
);
923 sendnoticetouser(proxyscannick
,np
,"Scan type Port Detections");
924 for (i
=0;i
<numscans
;i
++)
925 sendnoticetouser(proxyscannick
,np
,"%-9s %-5d %d (%.2f%%)",
926 scantostr(thescans
[ord
[i
]].type
), thescans
[ord
[i
]].port
, thescans
[ord
[i
]].hits
, ((float)thescans
[ord
[i
]].hits
*100)/totaldetects
);
928 sendnoticetouser(proxyscannick
,np
,"End of list.");
932 int proxyscandebug(void *sender
, int cargc
, char **cargv
) {
933 /* Dump all scans.. */
935 int activescansfound
=0;
936 int totalscansfound
=0;
938 nick
*np
= (nick
*)sender
;
940 sendnoticetouser(proxyscannick
,np
,"Active scans : %d",activescans
);
942 for (i
=0;i
<SCANHASHSIZE
;i
++) {
943 for (sp
=scantable
[i
];sp
;sp
=sp
->next
) {
944 if (sp
->outcome
==SOUTCOME_INPROGRESS
) {
948 sendnoticetouser(proxyscannick
,np
,"fd: %d type: %d port: %d state: %d outcome: %d IP: %s",
949 sp
->fd
,sp
->type
,sp
->port
,sp
->state
,sp
->outcome
,IPtostr(((patricia_node_t
*)sp
->node
)->prefix
->sin
));
953 sendnoticetouser(proxyscannick
,np
,"Total %d scans actually found (%d active)",totalscansfound
,activescansfound
);
957 void proxyscan_onconnect(int hooknum
, void *arg
) {
960 /* kick the queue.. */
964 int proxyscandosave(void *sender
, int cargc
, char **cargv
) {
965 nick
*np
= (nick
*)sender
;
967 sendnoticetouser(proxyscannick
,np
,"Saving cached hosts...");
968 dumpcachehosts(NULL
);
969 sendnoticetouser(proxyscannick
,np
,"Done.");
973 int proxyscandospew(void *sender
, int cargc
, char **cargv
) {
974 nick
*np
= (nick
*)sender
;
979 /* check our database for the ip supplied */
980 unsigned long a
,b
,c
,d
;
981 if (4 != sscanf(cargv
[0],"%lu.%lu.%lu.%lu",&a
,&b
,&c
,&d
)) {
982 sendnoticetouser(proxyscannick
,np
,"Usage: spew x.x.x.x");
985 proxyscanspewip(proxyscannick
,np
,a
,b
,c
,d
);
990 int proxyscandoshowkill(void *sender
, int cargc
, char **cargv
) {
991 nick
*np
= (nick
*)sender
;
996 /* check our database for the id supplied */
998 if (1 != sscanf(cargv
[0],"%lu",&a
)) {
999 sendnoticetouser(proxyscannick
,np
,"Usage: showkill <id>");
1002 proxyscanshowkill(proxyscannick
,np
,a
);
1007 void startnickscan(nick
*np
) {
1008 time_t t
= time(NULL
);
1010 for(i
=0;i
<numscans
;i
++) {
1011 /* @@@TODO: we allow a forced scan to scan the same IP multiple times atm */
1012 queuescan(np
->ipnode
,thescans
[i
].type
,thescans
[i
].port
,SCLASS_NORMAL
,t
);
1016 int proxyscandoscan(void *sender
, int cargc
, char **cargv
) {
1017 nick
*np
= (nick
*)sender
;
1018 patricia_node_t
*node
;
1019 struct irc_in_addr sin
;
1026 if (0 == ipmask_parse(cargv
[0],&sin
, &bits
)) {
1027 sendnoticetouser(proxyscannick
,np
,"Usage: scan <ip>");
1029 if (bits
!= 128 || !irc_in_addr_is_ipv4(&sin
) || irc_in_addr_is_loopback(&sin
)) {
1030 sendnoticetouser(proxyscannick
,np
,"You may only scan single IPv4 IP's");
1033 if (bits
!= 128 || irc_in_addr_is_loopback(&sin
)) {
1034 sendnoticetouser(proxyscannick
,np
,"You may only scan single IP's");
1039 sendnoticetouser(proxyscannick
,np
,"Forcing scan of %s",IPtostr(sin
));
1040 // * Just queue the scans directly here.. plonk them on the priority queue * /
1041 node
= refnode(iptree
, &sin
, bits
); /* node leaks node here - should only allow to scan a nick? */
1043 for(i
=0;i
<numscans
;i
++) {
1044 /* @@@TODO: we allow a forced scan to scan the same IP multiple times atm */
1045 queuescan(node
,thescans
[i
].type
,thescans
[i
].port
,SCLASS_NORMAL
,t
);
1051 int proxyscandoscanfile(void *sender
, int cargc
, char **cargv
) {
1052 nick
*np
= (nick
*)sender
;
1054 time_t t
= time(NULL
);
1055 int pscantypes
[PSCAN_MAXSCANS
];
1060 if ((fp
=fopen("data/doscan.txt","r"))==NULL
) {
1061 sendnoticetouser(proxyscannick
,np
,"Unable to open file for reading!");
1069 for(i
=0;i
<numscans
;i
++)
1070 if(thescans
[i
].type
> maxno
)
1071 maxno
= thescans
[i
].type
;
1073 tscantypes
= malloc(sizeof(int) * maxno
);
1074 for(i
=0;i
<maxno
;i
++)
1077 for(i
=0;i
<numscans
;i
++)
1078 tscantypes
[thescans
[i
].type
] = 1;
1080 for(i
=0,maxtypes
=0;i
<maxno
;i
++)
1082 pscantypes
[maxtypes
++] = i
;
1089 patricia_node_t
*node
;
1090 struct irc_in_addr sin
;
1092 unsigned short port
;
1093 char buf
[512], ip
[512];
1101 res
=sscanf(buf
,"%s %hu",ip
,&port
);
1106 if (0 == ipmask_parse(ip
,&sin
, &bits
)) {
1109 node
= refnode(iptree
, &sin
, bits
); /* LEAKS */
1111 for(i
=0;i
<maxtypes
;i
++) {
1112 queuescan(node
,pscantypes
[i
],port
,SCLASS_NORMAL
,t
);
1119 sendnoticetouser(proxyscannick
,np
,"Started %d scans...", count
);
1123 int proxyscandoaddscan(void *sender
, int cargc
, char **cargv
) {
1124 nick
*np
= (nick
*)sender
;
1130 if (sscanf(cargv
[0],"%u %u",&a
,&b
) != 2) {
1131 sendnoticetouser(proxyscannick
,np
,"Usage: addscan <type> <port>");
1133 sendnoticetouser(proxyscannick
,np
,"Added scan type %u port %u",a
,b
);
1134 proxyscan_addscantype(a
,b
);
1140 int proxyscandodelscan(void *sender
, int cargc
, char **cargv
) {
1141 nick
*np
= (nick
*)sender
;
1147 if (sscanf(cargv
[0],"%u %u",&a
,&b
) != 2) {
1148 sendnoticetouser(proxyscannick
,np
,"Usage: delscan <type> <port>");
1150 sendnoticetouser(proxyscannick
,np
,"Delete scan type %u port %u",a
,b
);
1151 proxyscan_delscantype(a
,b
);
1156 int proxyscandoshowcommands(void *sender
, int cargc
, char **cargv
) {
1157 nick
*np
= (nick
*)sender
;
1158 Command
*cmdlist
[100];
1161 n
=getcommandlist(ps_commands
,cmdlist
,100);
1163 sendnoticetouser(proxyscannick
,np
,"The following commands are registered at present:");
1165 sendnoticetouser(proxyscannick
,np
,"%s",cmdlist
[i
]->command
->content
);
1167 sendnoticetouser(proxyscannick
,np
,"End of list.");