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