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