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