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