]> jfr.im git - irc/quakenet/newserv.git/blame - proxyscan/proxyscan.c
Added 'showkill' and 'spew' commands (with associated functions) - also cleaned up...
[irc/quakenet/newserv.git] / proxyscan / proxyscan.c
CommitLineData
c86edd1d
Q
1
2#include "proxyscan.h"
3
4#include <sys/poll.h>
5#include <sys/types.h>
6#include <sys/socket.h>
7#include <netdb.h>
8#include "../core/error.h"
9#include "../core/events.h"
10#include <stdlib.h>
11#include <stdio.h>
12#include <errno.h>
13#include "../nick/nick.h"
14#include "../core/hooks.h"
15#include "../lib/sstring.h"
16#include "../irc/irc_config.h"
17#include "../localuser/localuser.h"
18#include "../core/config.h"
19#include <unistd.h>
20#include "../core/schedule.h"
21#include <string.h>
22#include "../irc/irc.h"
23#include "../lib/irc_string.h"
24
25#define SCANTIMEOUT 60
26
27#define SCANHOSTHASHSIZE 1000
28#define SCANHASHSIZE 400
29
30/* It's unlikely you'll get 100k of preamble before a connect... */
31#define READ_SANITY_LIMIT 102400
32
33scan *scantable[SCANHASHSIZE];
34
35int listenfd;
36int activescans;
37int maxscans;
38int queuedhosts;
39int scansdone;
40int rescaninterval;
41int warningsent;
42int glinedhosts;
43time_t starttime;
44
45int numscans; /* number of scan types currently valid */
46scantype thescans[PSCAN_MAXSCANS];
47
48unsigned int hitsbyclass[10];
49unsigned int scansbyclass[10];
50
51unsigned int myip;
52sstring *myipstr;
53unsigned short listenport;
54int brokendb;
55
56unsigned int ps_mailip;
57unsigned int ps_mailport;
58sstring *ps_mailname;
59
60nick *proxyscannick;
61
62FILE *ps_logfile;
63
64/* Local functions */
65void handlescansock(int fd, short events);
66void timeoutscansock(void *arg);
67void proxyscan_newnick(int hooknum, void *arg);
68void proxyscan_lostnick(int hooknum, void *arg);
69void proxyscanuserhandler(nick *target, int message, void **params);
70void registerproxyscannick();
71void killsock(scan *sp, int outcome);
72void killallscans();
73void proxyscanstats(int hooknum, void *arg);
74void sendlagwarning();
75void proxyscandostatus(nick *np);
76void proxyscandebug(nick *np);
77void proxyscan_newip(nick *np, unsigned long ip);
78int proxyscan_addscantype(int type, int port);
79int proxyscan_delscantype(int type, int port);
80
81int proxyscan_addscantype(int type, int port) {
82 /* Check we have a spare scan slot */
83
84 if (numscans>=PSCAN_MAXSCANS)
85 return 1;
86
87 thescans[numscans].type=type;
88 thescans[numscans].port=port;
89 thescans[numscans].hits=0;
90
91 numscans++;
92
93 return 0;
94}
95
96int proxyscan_delscantype(int type, int port) {
97 int i;
98
99 for (i=0;i<numscans;i++)
100 if (thescans[i].type==type && thescans[i].port==port)
101 break;
102
103 if (i>=numscans)
104 return 1;
105
106 memmove(thescans+i, thescans+(i+1), (PSCAN_MAXSCANS-(i+1)) * sizeof(scantype));
107 numscans--;
108
109 return 0;
110}
111
112void _init(void) {
113 sstring *cfgstr;
114 int ipbits[4];
115
116 memset(scantable,0,sizeof(scantable));
117 maxscans=200;
118 activescans=0;
119 queuedhosts=0;
120 scansdone=0;
121 warningsent=0;
122 starttime=time(NULL);
123 glinedhosts=0;
124
125 /* Listen port */
126 cfgstr=getcopyconfigitem("proxyscan","port","9999",6);
127 listenport=strtol(cfgstr->content,NULL,10);
128 freesstring(cfgstr);
129
130 /* Max concurrent scans */
131 cfgstr=getcopyconfigitem("proxyscan","maxscans","200",5);
132 maxscans=strtol(cfgstr->content,NULL,10);
133 freesstring(cfgstr);
134
135 /* Clean host timeout */
136 cfgstr=getcopyconfigitem("proxyscan","rescaninterval","3600",7);
137 rescaninterval=strtol(cfgstr->content,NULL,10);
138 cachehostinit(rescaninterval);
139 freesstring(cfgstr);
140
141 /* this default will NOT work well */
142 myipstr=getcopyconfigitem("proxyscan","ip","127.0.0.1",16);
143
144 sscanf(myipstr->content,"%d.%d.%d.%d",&ipbits[0],&ipbits[1],&ipbits[2],&ipbits[3]);
145
146 myip=((ipbits[0]&0xFF)<<24)+((ipbits[1]&0xFF)<<16)+
147 ((ipbits[2]&0xFF)<<8)+(ipbits[3]&0xFF);
148
149 /* Mailer host */
150 cfgstr=getcopyconfigitem("proxyscan","mailerip","",16);
151
152#if defined(PROXYSCAN_MAIL)
153 psm_mailerfd=-1;
154 if (cfgstr) {
155 sscanf(cfgstr->content,"%d.%d.%d.%d",&ipbits[0],&ipbits[1],&ipbits[2],&ipbits[3]);
156 ps_mailip = ((ipbits[0]&0xFF)<<24)+((ipbits[1]&0xFF)<<16)+
157 ((ipbits[2]&0xFF)<<8)+(ipbits[3]&0xFF);
158 ps_mailport=25;
159 freesstring(cfgstr);
160
161 ps_mailname=getcopyconfigitem("proxyscan","mailname","some.mail.server",HOSTLEN);
162 Error("proxyscan",ERR_INFO,"Proxyscan mailer enabled; mailing to %s as %s.",IPtostr(ps_mailip),ps_mailname->content);
163 } else {
164 ps_mailport=0;
165 ps_mailname=NULL;
166 }
167#endif
168
169 proxyscannick=NULL;
170 /* Set up our nick on the network */
171 scheduleoneshot(time(NULL),&registerproxyscannick,NULL);
172
173 registerhook(HOOK_NICK_NEWNICK,&proxyscan_newnick);
174
175 registerhook(HOOK_CORE_STATSREQUEST,&proxyscanstats);
176
177 /* Read in the clean hosts */
178 loadcachehosts();
179
180 /* Set up the database */
181 if ((proxyscandbinit())!=0) {
182 brokendb=1;
183 } else {
184 brokendb=0;
185 }
186
187 /* Default scan types */
188 proxyscan_addscantype(STYPE_HTTP, 8080);
189 proxyscan_addscantype(STYPE_HTTP, 80);
190 proxyscan_addscantype(STYPE_HTTP, 6588);
191 proxyscan_addscantype(STYPE_HTTP, 8000);
192 proxyscan_addscantype(STYPE_HTTP, 3128);
193 proxyscan_addscantype(STYPE_HTTP, 3802);
194 proxyscan_addscantype(STYPE_HTTP, 5490);
195 proxyscan_addscantype(STYPE_HTTP, 7441);
196 proxyscan_addscantype(STYPE_HTTP, 808);
197 proxyscan_addscantype(STYPE_HTTP, 3332);
198 proxyscan_addscantype(STYPE_HTTP, 2282);
199 proxyscan_addscantype(STYPE_SOCKS4, 1080);
200 proxyscan_addscantype(STYPE_SOCKS5, 1080);
201 proxyscan_addscantype(STYPE_SOCKS4, 1075);
202 proxyscan_addscantype(STYPE_SOCKS5, 1075);
203 proxyscan_addscantype(STYPE_SOCKS4, 2280);
204 proxyscan_addscantype(STYPE_SOCKS5, 2280);
205 proxyscan_addscantype(STYPE_SOCKS4, 1180);
206 proxyscan_addscantype(STYPE_SOCKS5, 1180);
207 proxyscan_addscantype(STYPE_WINGATE, 23);
208 proxyscan_addscantype(STYPE_CISCO, 23);
209 proxyscan_addscantype(STYPE_WINGATE, 1181);
210 proxyscan_addscantype(STYPE_SOCKS5, 1978);
211 proxyscan_addscantype(STYPE_SOCKS5, 1029);
212 proxyscan_addscantype(STYPE_SOCKS5, 3801);
213 proxyscan_addscantype(STYPE_SOCKS5, 3331);
214 proxyscan_addscantype(STYPE_HTTP, 65506);
215 proxyscan_addscantype(STYPE_HTTP, 63809);
905c2ba2 216 proxyscan_addscantype(STYPE_HTTP, 63000);
217 proxyscan_addscantype(STYPE_SOCKS4, 559);
218
c86edd1d
Q
219 /* Schedule saves */
220 schedulerecurring(time(NULL)+3600,0,3600,&dumpcachehosts,NULL);
221
222 ps_logfile=fopen("proxyscan.log","a");
223}
224
225void registerproxyscannick(void *arg) {
226 sstring *psnick,*psuser,*pshost,*psrealname;
227 /* Set up our nick on the network */
228
229 psnick=getcopyconfigitem("proxyscan","nick","P",NICKLEN);
230 psuser=getcopyconfigitem("proxyscan","user","proxyscan",USERLEN);
231 pshost=getcopyconfigitem("proxyscan","host","some.host",HOSTLEN);
232 psrealname=getcopyconfigitem("proxyscan","realname","Proxyscan",REALLEN);
233
234 proxyscannick=registerlocaluser(psnick->content,psuser->content,pshost->content,
235 psrealname->content,
236 NULL,UMODE_OPER|UMODE_SERVICE|UMODE_DEAF,
237 &proxyscanuserhandler);
238
239 freesstring(psnick);
240 freesstring(psuser);
241 freesstring(pshost);
242 freesstring(psrealname);
243}
244
245void _fini(void) {
246
247 deregisterlocaluser(proxyscannick,NULL);
248
249 deregisterhook(HOOK_NICK_NEWNICK,&proxyscan_newnick);
250
251 deregisterhook(HOOK_CORE_STATSREQUEST,&proxyscanstats);
252
253 deleteschedule(NULL,&dumpcachehosts,NULL);
254
255 /* Kill any scans in progress */
256 killallscans();
257
258 /* Dump the database - AFTER killallscans() which prunes it */
259 dumpcachehosts(NULL);
260
261 /* free() all our structures */
262 sfreeall();
263
264 freesstring(ps_mailname);
265#if defined(PROXYSCAN_MAIL)
266 if (psm_mailerfd!=-1)
267 deregisterhandler(psm_mailerfd,1);
268#endif
269
270 if (ps_logfile)
271 fclose(ps_logfile);
272}
273
274void proxyscanuserhandler(nick *target, int message, void **params) {
275 nick *sender;
276 char *msg;
277 int i;
278
279 switch(message) {
280 case LU_KILLED:
281 scheduleoneshot(time(NULL)+1,&registerproxyscannick,NULL);
282 proxyscannick=NULL;
283 break;
284
285 case LU_PRIVMSG:
286 case LU_SECUREMSG:
287 sender=(nick *)params[0];
288 msg=(char *)params[1];
289
290 if (IsOper(sender)) {
291 if (!ircd_strncmp(msg,"listopen",8)) {
292 proxyscandolistopen(proxyscannick,sender,time(NULL)-rescaninterval);
293 }
294
295 if (!ircd_strncmp(msg,"status",6)) {
296 proxyscandostatus(sender);
297 }
298
299 if (!ircd_strncmp(msg,"save",4)) {
300 dumpcachehosts(NULL);
301 sendnoticetouser(proxyscannick,sender,"Done.");
302 }
303
304 if (!ircd_strncmp(msg,"debug",5)) {
305 proxyscandebug(sender);
306 }
7d228b1d
D
307
308 if (!ircd_strncmp(msg,"spew ",5)) {
309 /* check our database for the ip supplied */
310 unsigned long a,b,c,d;
311 if (4 != sscanf(&msg[5],"%lu.%lu.%lu.%lu",&a,&b,&c,&d)) {
312 sendnoticetouser(proxyscannick,sender,"Usage: spew x.x.x.x");
313 } else {
314 /* check db */
315 proxyscanspewip(proxyscannick,sender,a,b,c,d);
316 }
317 }
318
319 if (!ircd_strncmp(msg,"showkill ",9)) {
320 /* check our database for the id supplied */
321 unsigned long a;
322 if (1 != sscanf(&msg[9],"%lu",&a)) {
323 sendnoticetouser(proxyscannick,sender,"Usage: showkill <id>");
324 } else {
325 /* check db */
326 proxyscanshowkill(proxyscannick,sender,a);
327 }
328 }
329
c86edd1d
Q
330 if (!ircd_strncmp(msg,"scan ",5)) {
331 unsigned long a,b,c,d;
332 if (4 != sscanf(&msg[5],"%lu.%lu.%lu.%lu",&a,&b,&c,&d)) {
333 sendnoticetouser(proxyscannick,sender,"Usage: scan a.b.c.d");
334 } else {
335 sendnoticetouser(proxyscannick,sender,"Forcing scan of %lu.%lu.%lu.%lu",a,b,c,d);
336 /* Just queue the scans directly here.. plonk them on the priority queue */
337 for(i=0;i<numscans;i++) {
338 queuescan((a<<24)+(b<<16)+(c<<8)+d,thescans[i].type,thescans[i].port,SCLASS_NORMAL,time(NULL));
339 }
340 }
341 }
342
343 if (!ircd_strncmp(msg,"addscan ",8)) {
344 unsigned int a,b;
345 if (sscanf(msg+8,"%u %u",&a,&b) != 2) {
346 sendnoticetouser(proxyscannick,sender,"Usage: addscan <type> <port>");
347 } else {
348 sendnoticetouser(proxyscannick,sender,"Added scan type %u port %u",a,b);
349 proxyscan_addscantype(a,b);
350 scanall(a,b);
351 }
352 }
353
354 if (!ircd_strncmp(msg,"delscan ",8)) {
355 unsigned int a,b;
356 if (sscanf(msg+8,"%u %u",&a,&b) != 2) {
357 sendnoticetouser(proxyscannick,sender,"Usage: delscan <type> <port>");
358 } else {
359 sendnoticetouser(proxyscannick,sender,"Delete scan type %u port %u",a,b);
360 proxyscan_delscantype(a,b);
361 }
362 }
363
7d228b1d 364 if ((!ircd_strncmp(msg,"help",4)) || (!ircd_strncmp(msg,"showcommands",12))) {
c86edd1d 365 sendnoticetouser(proxyscannick,sender,"Proxyscan commands:");
7d228b1d
D
366 sendnoticetouser(proxyscannick,sender,"----------------------------------------------------------------------");
367 sendnoticetouser(proxyscannick,sender,"help Shows this help");
368 sendnoticetouser(proxyscannick,sender,"status Prints status information");
369 sendnoticetouser(proxyscannick,sender,"listopen Shows open proxies found recently");
370 sendnoticetouser(proxyscannick,sender,"save Saves the clean host database");
371 sendnoticetouser(proxyscannick,sender,"scan <ip> Force scan of the supplied IP");
372 sendnoticetouser(proxyscannick,sender,"spew <ip> Find <ip> in our list of open proxies");
373 sendnoticetouser(proxyscannick,sender,"showkill <id> Shows details of a kill or gline made by the service");
c86edd1d
Q
374 }
375 }
376
377 default:
378 break;
379 }
380}
381
382void addscantohash(scan *sp) {
383 int hash;
384 hash=(sp->fd)%SCANHASHSIZE;
385
386 sp->next=scantable[hash];
387 scantable[hash]=sp;
388
389 activescans++;
390}
391
392void delscanfromhash(scan *sp) {
393 int hash;
394 scan **sh;
395
396 hash=(sp->fd)%SCANHASHSIZE;
397
398 for (sh=&(scantable[hash]);*sh;sh=&((*sh)->next)) {
399 if (*sh==sp) {
400 (*sh)=sp->next;
401 break;
402 }
403 }
404
405 activescans--;
406}
407
408scan *findscan(int fd) {
409 int hash;
410 scan *sp;
411
412 hash=fd%SCANHASHSIZE;
413
414 for (sp=scantable[hash];sp;sp=sp->next)
415 if (sp->fd==fd)
416 return sp;
417
418 return NULL;
419}
420
421void startscan(unsigned int IP, int type, int port, int class) {
422 scan *sp;
423
424 sp=getscan();
425
426 sp->outcome=SOUTCOME_INPROGRESS;
427 sp->port=port;
428 sp->IP=IP;
429 sp->type=type;
430 sp->class=class;
431 sp->bytesread=0;
432 sp->totalbytesread=0;
433 memset(sp->readbuf, '\0', PSCAN_READBUFSIZE);
434
435 sp->fd=createconnectsocket(sp->IP,sp->port);
436 sp->state=SSTATE_CONNECTING;
437 if (sp->fd<0) {
438 /* Couldn't set up the socket? */
439 freescan(sp);
440 return;
441 }
442 /* Wait until it is writeable */
443 registerhandler(sp->fd,POLLERR|POLLHUP|POLLOUT,&handlescansock);
444 /* And set a timeout */
445 sp->sch=scheduleoneshot(time(NULL)+SCANTIMEOUT,&timeoutscansock,(void *)sp);
446 addscantohash(sp);
447}
448
449void timeoutscansock(void *arg) {
450 scan *sp=(scan *)arg;
451
452 killsock(sp, SOUTCOME_CLOSED);
453}
454
455void killsock(scan *sp, int outcome) {
456 int i;
457 cachehost *chp;
458 foundproxy *fpp;
459
460 scansdone++;
461 scansbyclass[sp->class]++;
462
463 /* Remove the socket from the schedule/event lists */
464 deregisterhandler(sp->fd,1); /* this will close the fd for us */
465 deleteschedule(sp->sch,&timeoutscansock,(void *)sp);
466
467 sp->outcome=outcome;
468 delscanfromhash(sp);
469
470 /* See if we need to queue another scan.. */
471 if (sp->outcome==SOUTCOME_CLOSED &&
472 ((sp->class==SCLASS_CHECK) ||
473 (sp->class==SCLASS_NORMAL && (sp->state==SSTATE_SENTREQUEST || sp->state==SSTATE_GOTRESPONSE))))
474 queuescan(sp->IP, sp->type, sp->port, SCLASS_PASS2, time(NULL)+300);
475
476 if (sp->outcome==SOUTCOME_CLOSED && sp->class==SCLASS_PASS2)
477 queuescan(sp->IP, sp->type, sp->port, SCLASS_PASS3, time(NULL)+300);
478
479 if (sp->outcome==SOUTCOME_CLOSED && sp->class==SCLASS_PASS3)
480 queuescan(sp->IP, sp->type, sp->port, SCLASS_PASS4, time(NULL)+300);
481
482 if (sp->outcome==SOUTCOME_OPEN) {
483 hitsbyclass[sp->class]++;
484
485 /* Lets try and get the cache record. If there isn't one, make a new one. */
486 if (!(chp=findcachehost(sp->IP)))
487 chp=addcleanhost(sp->IP, time(NULL));
488
489 /* Stick it on the cache's list of proxies, if necessary */
490 for (fpp=chp->proxies;fpp;fpp=fpp->next)
491 if (fpp->type==sp->type && fpp->port==sp->port)
492 break;
493
494 if (!fpp) {
495 fpp=getfoundproxy();
496 fpp->type=sp->type;
497 fpp->port=sp->port;
498 fpp->next=chp->proxies;
499 chp->proxies=fpp;
500 }
501
502 if (!chp->glineid) {
503 glinedhosts++;
504 loggline(chp);
505 irc_send("%s GL * +*@%s 1800 :Open Proxy, see http://www.quakenet.org/openproxies.html - ID: %d",
506 mynumeric->content,IPtostr(sp->IP),chp->glineid);
507 Error("proxyscan",ERR_DEBUG,"Found open proxy on host %s",IPtostr(sp->IP));
508 } else {
509 loggline(chp); /* Update log only */
510 }
511
512 /* Update counter */
513 for(i=0;i<numscans;i++) {
514 if (thescans[i].type==sp->type && thescans[i].port==sp->port) {
515 thescans[i].hits++;
516 break;
517 }
518 }
519 }
520
521 freescan(sp);
522
523 /* kick the queue.. */
524 startqueuedscans();
525}
526
527void handlescansock(int fd, short events) {
528 scan *sp;
529 char buf[512];
530 int res;
531 int i;
532 unsigned long netip;
533 unsigned short netport;
534
535 if ((sp=findscan(fd))==NULL) {
536 /* Not found; return and hope it goes away */
537 Error("proxyscan",ERR_ERROR,"Unexpected message from fd %d",fd);
538 return;
539 }
540
541 /* It woke up, delete the alarm call.. */
542 deleteschedule(sp->sch,&timeoutscansock,(void *)sp);
543
544 if (events & (POLLERR|POLLHUP)) {
545 /* Some kind of error; give up on this socket */
546 if (sp->state==SSTATE_GOTRESPONSE) {
547 /* If the error occured while we were waiting for a response, we might have
548 * received the "OPEN PROXY!" message and the EOF at the same time, so continue
549 * processing */
550/* Error("proxyscan",ERR_DEBUG,"Got error in GOTRESPONSE state for %s, continuing.",IPtostr(sp->host->IP)); */
551 } else {
552 killsock(sp, SOUTCOME_CLOSED);
553 return;
554 }
555 }
556
557 /* Otherwise, we got what we wanted.. */
558
559 switch(sp->state) {
560 case SSTATE_CONNECTING:
561 /* OK, we got activity while connecting, so we're going to send some
562 * request depending on scan type. However, we can reregister everything
563 * here to save duplicate code: This code is common for all handlers */
564
565 /* Delete the old handler */
566 deregisterhandler(fd,0);
567 /* Set the new one */
568 registerhandler(fd,POLLERR|POLLHUP|POLLIN,&handlescansock);
569 sp->sch=scheduleoneshot(time(NULL)+SCANTIMEOUT,&timeoutscansock,(void *)sp);
570 /* Update state */
571 sp->state=SSTATE_SENTREQUEST;
572
573 switch(sp->type) {
574 case STYPE_HTTP:
575 sprintf(buf,"CONNECT %s:%d HTTP/1.0\r\n\r\n",myipstr->content,listenport);
576 if ((write(fd,buf,strlen(buf)))<strlen(buf)) {
577 /* We didn't write the full amount, DIE */
578 killsock(sp,SOUTCOME_CLOSED);
579 return;
580 }
581 break;
582
583 case STYPE_SOCKS4:
584 /* set up the buffer */
585 netip=htonl(myip);
586 netport=htons(listenport);
587 memcpy(&buf[4],&netip,4);
588 memcpy(&buf[2],&netport,2);
589 buf[0]=4;
590 buf[1]=1;
591 buf[8]=0;
592 if ((write(fd,buf,9))<9) {
593 /* Didn't write enough, give up */
594 killsock(sp,SOUTCOME_CLOSED);
595 return;
596 }
597 break;
598
599 case STYPE_SOCKS5:
600 /* Set up initial request buffer */
601 buf[0]=5;
602 buf[1]=1;
603 buf[2]=0;
604 if ((write(fd,buf,3))>3) {
605 /* Didn't write enough, give up */
606 killsock(sp,SOUTCOME_CLOSED);
607 return;
608 }
609
610 /* Now the actual connect request */
611 buf[0]=5;
612 buf[1]=1;
613 buf[2]=0;
614 buf[3]=1;
615 netip=htonl(myip);
616 netport=htons(listenport);
617 memcpy(&buf[4],&netip,4);
618 memcpy(&buf[8],&netport,2);
619 res=write(fd,buf,10);
620 if (res<10) {
621 killsock(sp,SOUTCOME_CLOSED);
622 return;
623 }
624 break;
625
626 case STYPE_WINGATE:
627 /* Send wingate request */
628 sprintf(buf,"%s:%d\r\n",myipstr->content,listenport);
629 if((write(fd,buf,strlen(buf)))<strlen(buf)) {
630 killsock(sp,SOUTCOME_CLOSED);
631 return;
632 }
633 break;
634
635 case STYPE_CISCO:
636 /* Send cisco request */
637 sprintf(buf,"cisco\r\n");
638 if ((write(fd,buf,strlen(buf)))<strlen(buf)) {
639 killsock(sp, SOUTCOME_CLOSED);
640 return;
641 }
642
643 sprintf(buf,"telnet %s %d\r\n",myipstr->content,listenport);
644 if ((write(fd,buf,strlen(buf)))<strlen(buf)) {
645 killsock(sp, SOUTCOME_CLOSED);
646 return;
647 }
648
905c2ba2 649 break;
650
651 case STYPE_DIRECT:
652 /* Do nothing */
c86edd1d
Q
653 break;
654 }
655 break;
656
657 case SSTATE_SENTREQUEST:
658 res=read(fd, sp->readbuf+sp->bytesread, PSCAN_READBUFSIZE-sp->bytesread);
659
660 if (res<=0) {
661 if ((errno!=EINTR && errno!=EWOULDBLOCK) || res==0) {
662 /* EOF, forget it */
663 killsock(sp, SOUTCOME_CLOSED);
664 return;
665 }
666 }
667
668 sp->bytesread+=res;
669 sp->totalbytesread+=res;
670 for (i=0;i<sp->bytesread - MAGICSTRINGLENGTH;i++) {
671 if (!strncmp(sp->readbuf+i, MAGICSTRING, MAGICSTRINGLENGTH)) {
672 /* Found the magic string */
673 /* If the offset is 0, this means it was the first thing we got from the socket,
674 * so it's an actual IRCD (sheesh). Note that when the buffer is full and moved,
675 * the thing moved to offset 0 would previously have been tested as offset
905c2ba2 676 * PSCAN_READBUFSIZE/2.
677 *
678 * Skip this checking for STYPE_DIRECT scans, which are used to detect trojans setting
679 * up portforwards (which will therefore show up as ircds, we rely on the port being
680 * strange enough to avoid false positives */
681 if (i==0 && (sp->type != STYPE_DIRECT)) {
c86edd1d
Q
682 killsock(sp, SOUTCOME_CLOSED);
683 return;
684 }
685
686 killsock(sp, SOUTCOME_OPEN);
687 return;
688 }
689 }
690
691 /* If the buffer is full, move half of it along to make room */
692 if (sp->bytesread == PSCAN_READBUFSIZE) {
693 memcpy(sp->readbuf, sp->readbuf + (PSCAN_READBUFSIZE)/2, PSCAN_READBUFSIZE/2);
694 sp->bytesread = PSCAN_READBUFSIZE/2;
695 }
696
697 /* Don't read data forever.. */
698 if (sp->totalbytesread > READ_SANITY_LIMIT) {
699 killsock(sp, SOUTCOME_CLOSED);
700 return;
701 }
702
703 /* No magic string yet, we schedule another timeout in case it comes later. */
704 sp->sch=scheduleoneshot(time(NULL)+SCANTIMEOUT,&timeoutscansock,(void *)sp);
705 return;
706 }
707}
708
709void killallscans() {
710 int i;
711 scan *sp;
712 cachehost *chp;
713
714 for(i=0;i<SCANHASHSIZE;i++) {
715 for(sp=scantable[i];sp;sp=sp->next) {
716 /* If there is a pending scan, delete it's clean host record.. */
717 if ((chp=findcachehost(sp->IP)) && !chp->proxies)
718 delcachehost(chp);
719
720 if (sp->fd!=-1) {
721 deregisterhandler(sp->fd,1);
722 deleteschedule(sp->sch,&timeoutscansock,(void *)(sp));
723 }
724 }
725 }
726}
727
728void proxyscanstats(int hooknum, void *arg) {
729 char buf[512];
730
731 sprintf(buf, "Proxyscn: %6d/%4d scans complete/in progress. %d hosts queued.",
732 scansdone,activescans,queuedhosts);
733 triggerhook(HOOK_CORE_STATSREPLY,buf);
734 sprintf(buf, "Proxyscn: %6u known clean hosts",cleancount());
735 triggerhook(HOOK_CORE_STATSREPLY,buf);
736}
737
738void sendlagwarning() {
739 int i,j;
740 nick *np;
741
742 for (i=0;i<MAXSERVERS;i++) {
743 if (serverlist[i].maxusernum>0) {
744 for(j=0;j<serverlist[i].maxusernum;j++) {
745 np=servernicks[i][j];
746 if (np!=NULL && IsOper(np)) {
747 sendnoticetouser(proxyscannick,np,"Warning: More than 20,000 hosts to scan - I'm lagging behind badly!");
748 }
749 }
750 }
751 }
752}
753
905c2ba2 754int pscansort(const void *a, const void *b) {
755 int ra = *((const int *)a);
756 int rb = *((const int *)b);
757
758 return thescans[ra].hits - thescans[rb].hits;
759}
760
c86edd1d
Q
761void proxyscandostatus(nick *np) {
762 int i;
763 int totaldetects=0;
905c2ba2 764 int ord[PSCAN_MAXSCANS];
c86edd1d
Q
765
766 sendnoticetouser(proxyscannick,np,"Service uptime: %s",longtoduration(time(NULL)-starttime, 1));
767 sendnoticetouser(proxyscannick,np,"Total scans completed: %d",scansdone);
768 sendnoticetouser(proxyscannick,np,"Total hosts glined: %d",glinedhosts);
769
770 sendnoticetouser(proxyscannick,np,"Currently active scans: %d/%d",activescans,maxscans);
771 sendnoticetouser(proxyscannick,np,"Normal queued scans: %d",normalqueuedscans);
772 sendnoticetouser(proxyscannick,np,"Timed queued scans: %d",prioqueuedscans);
773 sendnoticetouser(proxyscannick,np,"'Clean' cached hosts: %d",cleancount());
774 sendnoticetouser(proxyscannick,np,"'Dirty' cached hosts: %d",dirtycount());
775
776 for (i=0;i<5;i++)
777 sendnoticetouser(proxyscannick,np,"Open proxies, class %1d: %d/%d (%.2f%%)",i,hitsbyclass[i],scansbyclass[i],((float)hitsbyclass[i]*100)/scansbyclass[i]);
778
779 for (i=0;i<numscans;i++)
780 totaldetects+=thescans[i].hits;
781
905c2ba2 782 for (i=0;i<numscans;i++)
783 ord[i]=i;
784
785 qsort(ord,numscans,sizeof(int),pscansort);
786
c86edd1d
Q
787 sendnoticetouser(proxyscannick,np,"Scan type Port Detections");
788 for (i=0;i<numscans;i++)
789 sendnoticetouser(proxyscannick,np,"%-9s %-5d %d (%.2f%%)",
905c2ba2 790 scantostr(thescans[ord[i]].type), thescans[ord[i]].port, thescans[ord[i]].hits, ((float)thescans[ord[i]].hits*100)/totaldetects);
c86edd1d
Q
791
792 sendnoticetouser(proxyscannick,np,"End of list.");
793}
794
795void proxyscandebug(nick *np) {
796 /* Dump all scans.. */
797 int i;
798 int activescansfound=0;
799 int totalscansfound=0;
800 scan *sp;
801
802 sendnoticetouser(proxyscannick,np,"Active scans : %d",activescans);
803
804 for (i=0;i<SCANHASHSIZE;i++) {
805 for (sp=scantable[i];sp;sp=sp->next) {
806 if (sp->outcome==SOUTCOME_INPROGRESS) {
807 activescansfound++;
808 }
809 totalscansfound++;
810 sendnoticetouser(proxyscannick,np,"fd: %d type: %d port: %d state: %d outcome: %d IP: %s",
811 sp->fd,sp->type,sp->port,sp->state,sp->outcome,IPtostr(sp->IP));
812 }
813 }
814
815 sendnoticetouser(proxyscannick,np,"Total %d scans actually found (%d active)",totalscansfound,activescansfound);
816}