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