]> jfr.im git - irc/quakenet/newserv.git/blob - proxyscan/proxyscan.c
Merge default.
[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 <signal.h>
8 #include <netdb.h>
9 #include "../core/error.h"
10 #include "../core/events.h"
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include <errno.h>
14 #include "../nick/nick.h"
15 #include "../core/hooks.h"
16 #include "../lib/sstring.h"
17 #include "../irc/irc_config.h"
18 #include "../localuser/localuser.h"
19 #include "../core/config.h"
20 #include <unistd.h>
21 #include "../core/schedule.h"
22 #include <string.h>
23 #include "../irc/irc.h"
24 #include "../lib/irc_string.h"
25 #include "../lib/version.h"
26 #include "../channel/channel.h"
27 #include "../localuser/localuserchannel.h"
28 #include "../core/nsmalloc.h"
29 #include "../lib/irc_ipv6.h"
30 #include "../glines/glines.h"
31
32 MODULE_VERSION("")
33
34 #define SCANTIMEOUT 60
35
36 #define SCANHOSTHASHSIZE 1000
37 #define SCANHASHSIZE 400
38
39 /* It's unlikely you'll get 100k of preamble before a connect... */
40 #define READ_SANITY_LIMIT 102400
41
42 scan *scantable[SCANHASHSIZE];
43
44 CommandTree *ps_commands;
45
46 int listenfd;
47 int activescans;
48 int maxscans;
49 int queuedhosts;
50 int scansdone;
51 int rescaninterval;
52 int warningsent;
53 int glinedhosts;
54 time_t ps_starttime;
55 int ps_cache_ext;
56 int ps_extscan_ext;
57 int ps_ready;
58
59 int numscans; /* number of scan types currently valid */
60 scantype thescans[PSCAN_MAXSCANS];
61
62 unsigned int hitsbyclass[10];
63 unsigned int scansbyclass[10];
64
65 unsigned int myip;
66 sstring *myipstr;
67 unsigned short listenport;
68 int brokendb;
69
70 unsigned int ps_mailip;
71 unsigned int ps_mailport;
72 sstring *ps_mailname;
73
74 unsigned long scanspermin;
75 unsigned long tempscanspermin=0;
76 unsigned long lastscants=0;
77
78 unsigned int ps_start_ts=0;
79
80 nick *proxyscannick;
81
82 FILE *ps_logfile;
83
84 /* Local functions */
85 void handlescansock(int fd, short events);
86 void timeoutscansock(void *arg);
87 void proxyscan_newnick(int hooknum, void *arg);
88 void proxyscan_lostnick(int hooknum, void *arg);
89 void proxyscan_onconnect(int hooknum, void *arg);
90 void proxyscanuserhandler(nick *target, int message, void **params);
91 void registerproxyscannick();
92 void killsock(scan *sp, int outcome);
93 void killallscans();
94 void proxyscanstats(int hooknum, void *arg);
95 void sendlagwarning();
96 void proxyscan_newip(nick *np, unsigned long ip);
97 int proxyscan_addscantype(int type, int port);
98 int proxyscan_delscantype(int type, int port);
99
100 int proxyscandostatus(void *sender, int cargc, char **cargv);
101 int proxyscandebug(void *sender, int cargc, char **cargv);
102 int proxyscandosave(void *sender, int cargc, char **cargv);
103 int proxyscandospew(void *sender, int cargc, char **cargv);
104 int proxyscandoshowkill(void *sender, int cargc, char **cargv);
105 int proxyscandoscan(void *sender, int cargc, char **cargv);
106 int proxyscandoscanfile(void *sender, int cargc, char **cargv);
107 int proxyscandoaddscan(void *sender, int cargc, char **cargv);
108 int proxyscandodelscan(void *sender, int cargc, char **cargv);
109 int proxyscandoshowcommands(void *sender, int cargc, char **cargv);
110
111 int proxyscan_addscantype(int type, int port) {
112 /* Check we have a spare scan slot */
113
114 if (numscans>=PSCAN_MAXSCANS)
115 return 1;
116
117 thescans[numscans].type=type;
118 thescans[numscans].port=port;
119 thescans[numscans].hits=0;
120
121 numscans++;
122
123 return 0;
124 }
125
126 int proxyscan_delscantype(int type, int port) {
127 int i;
128
129 for (i=0;i<numscans;i++)
130 if (thescans[i].type==type && thescans[i].port==port)
131 break;
132
133 if (i>=numscans)
134 return 1;
135
136 memmove(thescans+i, thescans+(i+1), (PSCAN_MAXSCANS-(i+1)) * sizeof(scantype));
137 numscans--;
138
139 return 0;
140 }
141
142 void ignorepipe(int signal_) {
143 signal(SIGPIPE, ignorepipe); /* HACK */
144 }
145
146 void _init(void) {
147 sstring *cfgstr;
148 int ipbits[4];
149
150 signal(SIGPIPE, ignorepipe); /* HACK */
151
152 ps_start_ts = time(NULL);
153 ps_ready = 0;
154 ps_commands = NULL;
155
156 ps_cache_ext = registernodeext("proxyscancache");
157 if( ps_cache_ext == -1 ) {
158 Error("proxyscan",ERR_INFO,"failed to reg node ext");
159 return;
160 }
161 ps_extscan_ext = registernodeext("proxyscanextscan");
162 if ( ps_extscan_ext == -1) {
163 Error("proxyscan",ERR_INFO,"failed to reg node ext");
164 return;
165 }
166
167 memset(scantable,0,sizeof(scantable));
168 maxscans=200;
169 activescans=0;
170 queuedhosts=0;
171 scansdone=0;
172 warningsent=0;
173 ps_starttime=time(NULL);
174 glinedhosts=0;
175
176 scanspermin=0;
177 lastscants=time(NULL);
178
179 /* Listen port */
180 cfgstr=getcopyconfigitem("proxyscan","port","9999",6);
181 listenport=strtol(cfgstr->content,NULL,10);
182 freesstring(cfgstr);
183
184 /* Max concurrent scans */
185 cfgstr=getcopyconfigitem("proxyscan","maxscans","200",10);
186 maxscans=strtol(cfgstr->content,NULL,10);
187 freesstring(cfgstr);
188
189 /* Clean host timeout */
190 cfgstr=getcopyconfigitem("proxyscan","rescaninterval","3600",7);
191 rescaninterval=strtol(cfgstr->content,NULL,10);
192 cachehostinit(rescaninterval);
193 freesstring(cfgstr);
194
195 /* this default will NOT work well */
196 myipstr=getcopyconfigitem("proxyscan","ip","127.0.0.1",16);
197
198 sscanf(myipstr->content,"%d.%d.%d.%d",&ipbits[0],&ipbits[1],&ipbits[2],&ipbits[3]);
199
200 myip=((ipbits[0]&0xFF)<<24)+((ipbits[1]&0xFF)<<16)+
201 ((ipbits[2]&0xFF)<<8)+(ipbits[3]&0xFF);
202
203 #if defined(PROXYSCAN_MAIL)
204 /* Mailer host */
205 cfgstr=getcopyconfigitem("proxyscan","mailerip","",16);
206
207 psm_mailerfd=-1;
208 if (cfgstr) {
209 sscanf(cfgstr->content,"%d.%d.%d.%d",&ipbits[0],&ipbits[1],&ipbits[2],&ipbits[3]);
210 ps_mailip = ((ipbits[0]&0xFF)<<24)+((ipbits[1]&0xFF)<<16)+
211 ((ipbits[2]&0xFF)<<8)+(ipbits[3]&0xFF);
212 ps_mailport=25;
213 freesstring(cfgstr);
214
215 ps_mailname=getcopyconfigitem("proxyscan","mailname","some.mail.server",HOSTLEN);
216 Error("proxyscan",ERR_INFO,"Proxyscan mailer enabled; mailing to %s as %s.",IPlongtostr(ps_mailip),ps_mailname->content);
217 } else {
218 ps_mailport=0;
219 ps_mailname=NULL;
220 }
221 #endif
222
223 proxyscannick=NULL;
224 /* Set up our nick on the network */
225 scheduleoneshot(time(NULL),&registerproxyscannick,NULL);
226
227 registerhook(HOOK_SERVER_END_OF_BURST, &proxyscan_onconnect);
228
229 registerhook(HOOK_NICK_NEWNICK,&proxyscan_newnick);
230
231 registerhook(HOOK_CORE_STATSREQUEST,&proxyscanstats);
232
233 /* Read in the clean hosts */
234 loadcachehosts();
235
236 /* Read in any custom ports to scan */
237 loadextrascans();
238
239 /* Set up the database */
240 if ((proxyscandbinit())!=0) {
241 brokendb=1;
242 } else {
243 brokendb=0;
244 }
245
246 ps_commands = newcommandtree();
247 addcommandtotree(ps_commands, "showcommands", 0, 0, &proxyscandoshowcommands);
248 addcommandtotree(ps_commands, "status", 0, 0, &proxyscandostatus);
249 addcommandtotree(ps_commands, "listopen", 0, 0, &proxyscandolistopen);
250 addcommandtotree(ps_commands, "save", 0, 0, &proxyscandosave);
251 addcommandtotree(ps_commands, "spew", 0, 1, &proxyscandospew);
252 addcommandtotree(ps_commands, "showkill", 0, 1, &proxyscandoshowkill);
253 addcommandtotree(ps_commands, "scan", 0, 1, &proxyscandoscan);
254 addcommandtotree(ps_commands, "scanfile", 0, 1, &proxyscandoscanfile);
255 addcommandtotree(ps_commands, "addscan", 0, 1, &proxyscandoaddscan);
256 addcommandtotree(ps_commands, "delscan", 0, 1, &proxyscandodelscan);
257
258 /* Default scan types */
259 proxyscan_addscantype(STYPE_HTTP, 8080);
260 proxyscan_addscantype(STYPE_HTTP, 8118);
261 proxyscan_addscantype(STYPE_HTTP, 80);
262 proxyscan_addscantype(STYPE_HTTP, 6588);
263 proxyscan_addscantype(STYPE_HTTP, 8000);
264 proxyscan_addscantype(STYPE_HTTP, 3128);
265 proxyscan_addscantype(STYPE_HTTP, 3802);
266 proxyscan_addscantype(STYPE_HTTP, 5490);
267 proxyscan_addscantype(STYPE_HTTP, 7441);
268 proxyscan_addscantype(STYPE_HTTP, 808);
269 proxyscan_addscantype(STYPE_HTTP, 3332);
270 proxyscan_addscantype(STYPE_HTTP, 2282);
271
272 proxyscan_addscantype(STYPE_HTTP, 1644);
273 proxyscan_addscantype(STYPE_HTTP, 8081);
274 proxyscan_addscantype(STYPE_HTTP, 443);
275 proxyscan_addscantype(STYPE_HTTP, 1337);
276 proxyscan_addscantype(STYPE_HTTP, 8888);
277 proxyscan_addscantype(STYPE_HTTP, 8008);
278 proxyscan_addscantype(STYPE_HTTP, 6515);
279 proxyscan_addscantype(STYPE_HTTP, 27977);
280
281 proxyscan_addscantype(STYPE_SOCKS4, 559);
282 proxyscan_addscantype(STYPE_SOCKS4, 1080);
283 proxyscan_addscantype(STYPE_SOCKS5, 1080);
284 proxyscan_addscantype(STYPE_SOCKS4, 1075);
285 proxyscan_addscantype(STYPE_SOCKS5, 1075);
286 proxyscan_addscantype(STYPE_SOCKS4, 2280);
287 proxyscan_addscantype(STYPE_SOCKS5, 2280);
288 proxyscan_addscantype(STYPE_SOCKS4, 1180);
289 proxyscan_addscantype(STYPE_SOCKS5, 1180);
290 proxyscan_addscantype(STYPE_SOCKS4, 9999);
291 proxyscan_addscantype(STYPE_SOCKS5, 9999);
292 proxyscan_addscantype(STYPE_WINGATE, 23);
293 proxyscan_addscantype(STYPE_CISCO, 23);
294 proxyscan_addscantype(STYPE_WINGATE, 1181);
295 proxyscan_addscantype(STYPE_SOCKS5, 1978);
296 proxyscan_addscantype(STYPE_SOCKS5, 1029);
297 proxyscan_addscantype(STYPE_SOCKS5, 3801);
298 proxyscan_addscantype(STYPE_SOCKS5, 3331);
299 proxyscan_addscantype(STYPE_HTTP, 65506);
300 proxyscan_addscantype(STYPE_HTTP, 63809);
301 proxyscan_addscantype(STYPE_HTTP, 63000);
302 proxyscan_addscantype(STYPE_SOCKS4, 29992);
303 proxyscan_addscantype(STYPE_DIRECT_IRC, 6666);
304 proxyscan_addscantype(STYPE_DIRECT_IRC, 6667);
305 proxyscan_addscantype(STYPE_DIRECT_IRC, 6668);
306 proxyscan_addscantype(STYPE_DIRECT_IRC, 6669);
307 proxyscan_addscantype(STYPE_DIRECT_IRC, 6670);
308 proxyscan_addscantype(STYPE_ROUTER, 3128);
309 proxyscan_addscantype(STYPE_SOCKS5, 27977);
310
311 /* Schedule saves */
312 schedulerecurring(time(NULL)+3600,0,3600,&dumpcachehosts,NULL);
313
314 ps_logfile=fopen("logs/proxyscan.log","a");
315
316 if (connected) {
317 /* if we're already connected, assume we're just reloading module (i.e. have a completed burst) */
318 ps_ready = 1;
319 startqueuedscans();
320 }
321 }
322
323 void registerproxyscannick(void *arg) {
324 sstring *psnick,*psuser,*pshost,*psrealname;
325 /* Set up our nick on the network */
326 channel *cp;
327
328 psnick=getcopyconfigitem("proxyscan","nick","P",NICKLEN);
329 psuser=getcopyconfigitem("proxyscan","user","proxyscan",USERLEN);
330 pshost=getcopyconfigitem("proxyscan","host","some.host",HOSTLEN);
331 psrealname=getcopyconfigitem("proxyscan","realname","Proxyscan",REALLEN);
332
333 proxyscannick=registerlocaluser(psnick->content,psuser->content,pshost->content,
334 psrealname->content,
335 NULL,UMODE_OPER|UMODE_SERVICE|UMODE_DEAF,
336 &proxyscanuserhandler);
337
338 freesstring(psnick);
339 freesstring(psuser);
340 freesstring(pshost);
341 freesstring(psrealname);
342
343 cp=findchannel("#twilightzone");
344 if (!cp) {
345 localcreatechannel(proxyscannick,"#twilightzone");
346 } else {
347 localjoinchannel(proxyscannick,cp);
348 localgetops(proxyscannick,cp);
349 }
350 }
351
352 void _fini(void) {
353
354 deregisterlocaluser(proxyscannick,NULL);
355
356 deregisterhook(HOOK_SERVER_END_OF_BURST, &proxyscan_onconnect);
357
358 deregisterhook(HOOK_NICK_NEWNICK,&proxyscan_newnick);
359
360 deregisterhook(HOOK_CORE_STATSREQUEST,&proxyscanstats);
361
362 deleteschedule(NULL,&dumpcachehosts,NULL);
363
364 destroycommandtree(ps_commands);
365
366 /* Kill any scans in progress */
367 killallscans();
368
369 /* Dump the database - AFTER killallscans() which prunes it */
370 dumpcachehosts(NULL);
371
372 /* dump any cached hosts before deleting the extensions */
373 releasenodeext(ps_cache_ext);
374 releasenodeext(ps_extscan_ext);
375
376 /* free() all our structures */
377 nsfreeall(POOL_PROXYSCAN);
378
379 freesstring(myipstr);
380 freesstring(ps_mailname);
381 #if defined(PROXYSCAN_MAIL)
382 if (psm_mailerfd!=-1)
383 deregisterhandler(psm_mailerfd,1);
384 #endif
385
386 if (ps_logfile)
387 fclose(ps_logfile);
388 }
389
390 void proxyscanuserhandler(nick *target, int message, void **params) {
391 nick *sender;
392 Command *ps_command;
393 char *cargv[20];
394 int cargc;
395
396 switch(message) {
397 case LU_KILLED:
398 scheduleoneshot(time(NULL)+1,&registerproxyscannick,NULL);
399 proxyscannick=NULL;
400 break;
401
402 case LU_PRIVMSG:
403 case LU_SECUREMSG:
404 sender=(nick *)params[0];
405
406 if (IsOper(sender)) {
407 cargc = splitline((char *)params[1], cargv, 20, 0);
408
409 if ( cargc == 0 )
410 return;
411
412 ps_command = findcommandintree(ps_commands, cargv[0], 1);
413
414 if ( !ps_command ) {
415 sendnoticetouser(proxyscannick,sender, "Unknown command.");
416 return;
417 }
418
419 if ( ps_command->maxparams < (cargc-1) ) {
420 rejoinline(cargv[ps_command->maxparams], cargc - (ps_command->maxparams));
421 cargc = (ps_command->maxparams) + 1;
422 }
423
424 (ps_command->handler)((void *)sender, cargc - 1, &(cargv[1]));
425 break;
426 }
427
428 default:
429 break;
430 }
431 }
432
433 void addscantohash(scan *sp) {
434 int hash;
435 hash=(sp->fd)%SCANHASHSIZE;
436
437 sp->next=scantable[hash];
438 scantable[hash]=sp;
439
440 activescans++;
441 }
442
443 void delscanfromhash(scan *sp) {
444 int hash;
445 scan **sh;
446
447 hash=(sp->fd)%SCANHASHSIZE;
448
449 for (sh=&(scantable[hash]);*sh;sh=&((*sh)->next)) {
450 if (*sh==sp) {
451 (*sh)=sp->next;
452 break;
453 }
454 }
455
456 activescans--;
457 }
458
459 scan *findscan(int fd) {
460 int hash;
461 scan *sp;
462
463 hash=fd%SCANHASHSIZE;
464
465 for (sp=scantable[hash];sp;sp=sp->next)
466 if (sp->fd==fd)
467 return sp;
468
469 return NULL;
470 }
471
472 void startscan(patricia_node_t *node, int type, int port, int class) {
473 scan *sp;
474 float scantmp;
475
476 if (scansdone>maxscans)
477 {
478 /* ignore the first maxscans as this will skew our scans per second! */
479 tempscanspermin++;
480 if ((lastscants+60) <= time(NULL))
481 {
482 /* ok, at least 60 seconds has passed, calculate the scans per minute figure */
483 scantmp = time(NULL) - lastscants;
484 scantmp = tempscanspermin / scantmp;
485 scantmp = (scantmp * 60);
486 scanspermin = scantmp;
487 lastscants = time(NULL);
488 tempscanspermin = 0;
489 }
490 }
491
492 sp=getscan();
493
494 sp->outcome=SOUTCOME_INPROGRESS;
495 sp->port=port;
496 sp->node=node;
497 sp->type=type;
498 sp->class=class;
499 sp->bytesread=0;
500 sp->totalbytesread=0;
501 memset(sp->readbuf, '\0', PSCAN_READBUFSIZE);
502
503 sp->fd=createconnectsocket(&((patricia_node_t *)sp->node)->prefix->sin,sp->port);
504 sp->state=SSTATE_CONNECTING;
505 if (sp->fd<0) {
506 /* Couldn't set up the socket? */
507 derefnode(iptree,sp->node);
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 time_t now;
529 char reason[200];
530
531 scansdone++;
532 scansbyclass[sp->class]++;
533
534 /* Remove the socket from the schedule/event lists */
535 deregisterhandler(sp->fd,1); /* this will close the fd for us */
536 deleteschedule(sp->sch,&timeoutscansock,(void *)sp);
537
538 sp->outcome=outcome;
539 delscanfromhash(sp);
540
541 /* See if we need to queue another scan.. */
542 if (sp->outcome==SOUTCOME_CLOSED &&
543 ((sp->class==SCLASS_CHECK) ||
544 (sp->class==SCLASS_NORMAL && (sp->state==SSTATE_SENTREQUEST || sp->state==SSTATE_GOTRESPONSE))))
545 queuescan(sp->node, sp->type, sp->port, SCLASS_PASS2, time(NULL)+300);
546
547 if (sp->outcome==SOUTCOME_CLOSED && sp->class==SCLASS_PASS2)
548 queuescan(sp->node, sp->type, sp->port, SCLASS_PASS3, time(NULL)+300);
549
550 if (sp->outcome==SOUTCOME_CLOSED && sp->class==SCLASS_PASS3)
551 queuescan(sp->node, sp->type, sp->port, SCLASS_PASS4, time(NULL)+300);
552
553 if (sp->outcome==SOUTCOME_OPEN) {
554 hitsbyclass[sp->class]++;
555
556 /* Lets try and get the cache record. If there isn't one, make a new one. */
557 if (!(chp=findcachehost(sp->node))) {
558 chp=addcleanhost(time(NULL));
559 patricia_ref_prefix(sp->node->prefix);
560 sp->node->exts[ps_cache_ext] = chp;
561 }
562 /* Stick it on the cache's list of proxies, if necessary */
563 for (fpp=chp->proxies;fpp;fpp=fpp->next)
564 if (fpp->type==sp->type && fpp->port==sp->port)
565 break;
566
567 if (!fpp) {
568 fpp=getfoundproxy();
569 fpp->type=sp->type;
570 fpp->port=sp->port;
571 fpp->next=chp->proxies;
572 chp->proxies=fpp;
573 }
574
575 now=time(NULL);
576 /* the purpose of this lastgline stuff is to stop gline spam from one scan */
577 if (!chp->glineid || (now>=chp->lastgline+SCANTIMEOUT)) {
578 char buf[512];
579 struct irc_in_addr *ip;
580
581 chp->lastgline=now;
582 glinedhosts++;
583
584 loggline(chp, sp->node);
585 ip = &(((patricia_node_t *)sp->node)->prefix->sin);
586 snprintf(reason, sizeof(reason), "Open Proxy, see http://www.quakenet.org/openproxies.html - ID: %d", chp->glineid);
587 glinebyip("*", ip, 128, 1800, reason, GLINE_IGNORE_TRUST, "proxyscan");
588 Error("proxyscan",ERR_DEBUG,"Found open proxy on host %s",IPtostr(*ip));
589
590 snprintf(buf, sizeof(buf), "proxy-gline %lu %s %s %hu %s", time(NULL), IPtostr(*ip), scantostr(sp->type), sp->port, "irc.quakenet.org");
591 triggerhook(HOOK_SHADOW_SERVER, (void *)buf);
592 } else {
593 loggline(chp, sp->node); /* Update log only */
594 }
595
596 /* Update counter */
597 for(i=0;i<numscans;i++) {
598 if (thescans[i].type==sp->type && thescans[i].port==sp->port) {
599 thescans[i].hits++;
600 break;
601 }
602 }
603 }
604
605 /* deref prefix (referenced in queuescan) */
606 derefnode(iptree,sp->node);
607 freescan(sp);
608
609 /* kick the queue.. */
610 startqueuedscans();
611 }
612
613 void handlescansock(int fd, short events) {
614 scan *sp;
615 char buf[512];
616 int res;
617 int i;
618 unsigned long netip;
619 unsigned short netport;
620
621 if ((sp=findscan(fd))==NULL) {
622 /* Not found; return and hope it goes away */
623 Error("proxyscan",ERR_ERROR,"Unexpected message from fd %d",fd);
624 return;
625 }
626
627 /* It woke up, delete the alarm call.. */
628 deleteschedule(sp->sch,&timeoutscansock,(void *)sp);
629
630 if (events & (POLLERR|POLLHUP)) {
631 /* Some kind of error; give up on this socket */
632 if (sp->state==SSTATE_GOTRESPONSE) {
633 /* If the error occured while we were waiting for a response, we might have
634 * received the "OPEN PROXY!" message and the EOF at the same time, so continue
635 * processing */
636 /* Error("proxyscan",ERR_DEBUG,"Got error in GOTRESPONSE state for %s, continuing.",IPtostr(sp->host->IP)); */
637 } else {
638 killsock(sp, SOUTCOME_CLOSED);
639 return;
640 }
641 }
642
643 /* Otherwise, we got what we wanted.. */
644
645 switch(sp->state) {
646 case SSTATE_CONNECTING:
647 /* OK, we got activity while connecting, so we're going to send some
648 * request depending on scan type. However, we can reregister everything
649 * here to save duplicate code: This code is common for all handlers */
650
651 /* Delete the old handler */
652 deregisterhandler(fd,0);
653 /* Set the new one */
654 registerhandler(fd,POLLERR|POLLHUP|POLLIN,&handlescansock);
655 sp->sch=scheduleoneshot(time(NULL)+SCANTIMEOUT,&timeoutscansock,(void *)sp);
656 /* Update state */
657 sp->state=SSTATE_SENTREQUEST;
658
659 switch(sp->type) {
660 case STYPE_HTTP:
661 sprintf(buf,"CONNECT %s:%d HTTP/1.0\r\n\r\n\r\n",myipstr->content,listenport);
662 if ((write(fd,buf,strlen(buf)))<strlen(buf)) {
663 /* We didn't write the full amount, DIE */
664 killsock(sp,SOUTCOME_CLOSED);
665 return;
666 }
667 break;
668
669 case STYPE_SOCKS4:
670 /* set up the buffer */
671 netip=htonl(myip);
672 netport=htons(listenport);
673 memcpy(&buf[4],&netip,4);
674 memcpy(&buf[2],&netport,2);
675 buf[0]=4;
676 buf[1]=1;
677 buf[8]=0;
678 if ((write(fd,buf,9))<9) {
679 /* Didn't write enough, give up */
680 killsock(sp,SOUTCOME_CLOSED);
681 return;
682 }
683 break;
684
685 case STYPE_SOCKS5:
686 /* Set up initial request buffer */
687 buf[0]=5;
688 buf[1]=1;
689 buf[2]=0;
690 if ((write(fd,buf,3))>3) {
691 /* Didn't write enough, give up */
692 killsock(sp,SOUTCOME_CLOSED);
693 return;
694 }
695
696 /* Now the actual connect request */
697 buf[0]=5;
698 buf[1]=1;
699 buf[2]=0;
700 buf[3]=1;
701 netip=htonl(myip);
702 netport=htons(listenport);
703 memcpy(&buf[4],&netip,4);
704 memcpy(&buf[8],&netport,2);
705 res=write(fd,buf,10);
706 if (res<10) {
707 killsock(sp,SOUTCOME_CLOSED);
708 return;
709 }
710 break;
711
712 case STYPE_WINGATE:
713 /* Send wingate request */
714 sprintf(buf,"%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 break;
720
721 case STYPE_CISCO:
722 /* Send cisco request */
723 sprintf(buf,"cisco\r\n");
724 if ((write(fd,buf,strlen(buf)))<strlen(buf)) {
725 killsock(sp, SOUTCOME_CLOSED);
726 return;
727 }
728
729 sprintf(buf,"telnet %s %d\r\n",myipstr->content,listenport);
730 if ((write(fd,buf,strlen(buf)))<strlen(buf)) {
731 killsock(sp, SOUTCOME_CLOSED);
732 return;
733 }
734
735 break;
736
737 case STYPE_DIRECT:
738 /* Do nothing */
739 break;
740
741 case STYPE_DIRECT_IRC:
742 sprintf(buf,"PRIVMSG\r\n");
743 if ((write(fd,buf,strlen(buf)))<strlen(buf)) {
744 killsock(sp, SOUTCOME_CLOSED);
745 return;
746 }
747
748 /* Do nothing */
749 break;
750
751 case STYPE_ROUTER:
752 sprintf(buf,"GET /nonexistent HTTP/1.0\r\n\r\n");
753 if ((write(fd,buf,strlen(buf)))<strlen(buf)) {
754 killsock(sp, SOUTCOME_CLOSED);
755 return;
756 }
757
758 /* Do nothing */
759 break;
760 }
761 break;
762
763 case SSTATE_SENTREQUEST:
764 res=read(fd, sp->readbuf+sp->bytesread, PSCAN_READBUFSIZE-sp->bytesread);
765
766 if (res<=0) {
767 if ((errno!=EINTR && errno!=EWOULDBLOCK) || res==0) {
768 /* EOF, forget it */
769 killsock(sp, SOUTCOME_CLOSED);
770 return;
771 }
772 }
773
774 sp->bytesread+=res;
775 sp->totalbytesread+=res;
776
777 {
778 char *magicstring;
779 int magicstringlength;
780
781 if(sp->type == STYPE_DIRECT_IRC) {
782 magicstring = MAGICIRCSTRING;
783 magicstringlength = MAGICIRCSTRINGLENGTH;
784 } else if(sp->type == STYPE_ROUTER) {
785 magicstring = MAGICROUTERSTRING;
786 magicstringlength = MAGICROUTERSTRINGLENGTH;
787 } else {
788 magicstring = MAGICSTRING;
789 magicstringlength = MAGICSTRINGLENGTH;
790 if(sp->totalbytesread - res == 0) {
791 buf[0] = '\n';
792 write(fd,buf,1);
793 }
794 }
795
796 for (i=0;i<sp->bytesread - magicstringlength;i++) {
797 if (!strncmp(sp->readbuf+i, magicstring, magicstringlength)) {
798 /* Found the magic string */
799 /* If the offset is 0, this means it was the first thing we got from the socket,
800 * so it's an actual IRCD (sheesh). Note that when the buffer is full and moved,
801 * the thing moved to offset 0 would previously have been tested as offset
802 * PSCAN_READBUFSIZE/2.
803 *
804 * Skip this checking for STYPE_DIRECT scans, which are used to detect trojans setting
805 * up portforwards (which will therefore show up as ircds, we rely on the port being
806 * strange enough to avoid false positives */
807 if (i==0 && (sp->type != STYPE_DIRECT)) {
808 killsock(sp, SOUTCOME_CLOSED);
809 return;
810 }
811
812 killsock(sp, SOUTCOME_OPEN);
813 return;
814 }
815 }
816 }
817
818 /* If the buffer is full, move half of it along to make room */
819 if (sp->bytesread == PSCAN_READBUFSIZE) {
820 memcpy(sp->readbuf, sp->readbuf + (PSCAN_READBUFSIZE)/2, PSCAN_READBUFSIZE/2);
821 sp->bytesread = PSCAN_READBUFSIZE/2;
822 }
823
824 /* Don't read data forever.. */
825 if (sp->totalbytesread > READ_SANITY_LIMIT) {
826 killsock(sp, SOUTCOME_CLOSED);
827 return;
828 }
829
830 /* No magic string yet, we schedule another timeout in case it comes later. */
831 sp->sch=scheduleoneshot(time(NULL)+SCANTIMEOUT,&timeoutscansock,(void *)sp);
832 return;
833 }
834 }
835
836 void killallscans() {
837 int i;
838 scan *sp;
839 cachehost *chp;
840
841 for(i=0;i<SCANHASHSIZE;i++) {
842 for(sp=scantable[i];sp;sp=sp->next) {
843 /* If there is a pending scan, delete it's clean host record.. */
844 if ((chp=findcachehost(sp->node)) && !chp->proxies) {
845 sp->node->exts[ps_cache_ext] = NULL;
846 derefnode(iptree,sp->node);
847 delcachehost(chp);
848 }
849
850 if (sp->fd!=-1) {
851 deregisterhandler(sp->fd,1);
852 deleteschedule(sp->sch,&timeoutscansock,(void *)(sp));
853 }
854 }
855 }
856 }
857
858 void proxyscanstats(int hooknum, void *arg) {
859 char buf[512];
860
861 sprintf(buf, "Proxyscn: %6d/%4d scans complete/in progress. %d hosts queued.",
862 scansdone,activescans,queuedhosts);
863 triggerhook(HOOK_CORE_STATSREPLY,buf);
864 sprintf(buf, "Proxyscn: %6u known clean hosts",cleancount());
865 triggerhook(HOOK_CORE_STATSREPLY,buf);
866 }
867
868 void sendlagwarning() {
869 int i,j;
870 nick *np;
871
872 for (i=0;i<MAXSERVERS;i++) {
873 if (serverlist[i].maxusernum>0) {
874 for(j=0;j<serverlist[i].maxusernum;j++) {
875 np=servernicks[i][j];
876 if (np!=NULL && IsOper(np)) {
877 sendnoticetouser(proxyscannick,np,"Warning: More than 20,000 hosts to scan - I'm lagging behind badly!");
878 }
879 }
880 }
881 }
882 }
883
884 int pscansort(const void *a, const void *b) {
885 int ra = *((const int *)a);
886 int rb = *((const int *)b);
887
888 return thescans[ra].hits - thescans[rb].hits;
889 }
890
891 int proxyscandostatus(void *sender, int cargc, char **cargv) {
892 nick *np = (nick *) sender;
893 int i;
894 int totaldetects=0;
895 int ord[PSCAN_MAXSCANS];
896
897 sendnoticetouser(proxyscannick,np,"Service uptime: %s",longtoduration(time(NULL)-ps_starttime, 1));
898 sendnoticetouser(proxyscannick,np,"Total scans completed: %d",scansdone);
899 sendnoticetouser(proxyscannick,np,"Total hosts glined: %d",glinedhosts);
900
901 sendnoticetouser(proxyscannick,np,"pendingscan structures: %lu x %lu bytes = %lu bytes total",countpendingscan,
902 sizeof(pendingscan), (countpendingscan * sizeof(pendingscan)));
903
904 sendnoticetouser(proxyscannick,np,"Currently active scans: %d/%d",activescans,maxscans);
905 sendnoticetouser(proxyscannick,np,"Processing speed: %lu scans per minute",scanspermin);
906 sendnoticetouser(proxyscannick,np,"Normal queued scans: %d",normalqueuedscans);
907 sendnoticetouser(proxyscannick,np,"Timed queued scans: %d",prioqueuedscans);
908 sendnoticetouser(proxyscannick,np,"'Clean' cached hosts: %d",cleancount());
909 sendnoticetouser(proxyscannick,np,"'Dirty' cached hosts: %d",dirtycount());
910
911 sendnoticetouser(proxyscannick,np,"Extra scans: %d", extrascancount());
912 for (i=0;i<5;i++)
913 sendnoticetouser(proxyscannick,np,"Open proxies, class %1d: %d/%d (%.2f%%)",i,hitsbyclass[i],scansbyclass[i],((float)hitsbyclass[i]*100)/scansbyclass[i]);
914
915 for (i=0;i<numscans;i++)
916 totaldetects+=thescans[i].hits;
917
918 for (i=0;i<numscans;i++)
919 ord[i]=i;
920
921 qsort(ord,numscans,sizeof(int),pscansort);
922
923 sendnoticetouser(proxyscannick,np,"Scan type Port Detections");
924 for (i=0;i<numscans;i++)
925 sendnoticetouser(proxyscannick,np,"%-9s %-5d %d (%.2f%%)",
926 scantostr(thescans[ord[i]].type), thescans[ord[i]].port, thescans[ord[i]].hits, ((float)thescans[ord[i]].hits*100)/totaldetects);
927
928 sendnoticetouser(proxyscannick,np,"End of list.");
929 return CMD_OK;
930 }
931
932 int proxyscandebug(void *sender, int cargc, char **cargv) {
933 /* Dump all scans.. */
934 int i;
935 int activescansfound=0;
936 int totalscansfound=0;
937 scan *sp;
938 nick *np = (nick *)sender;
939
940 sendnoticetouser(proxyscannick,np,"Active scans : %d",activescans);
941
942 for (i=0;i<SCANHASHSIZE;i++) {
943 for (sp=scantable[i];sp;sp=sp->next) {
944 if (sp->outcome==SOUTCOME_INPROGRESS) {
945 activescansfound++;
946 }
947 totalscansfound++;
948 sendnoticetouser(proxyscannick,np,"fd: %d type: %d port: %d state: %d outcome: %d IP: %s",
949 sp->fd,sp->type,sp->port,sp->state,sp->outcome,IPtostr(((patricia_node_t *)sp->node)->prefix->sin));
950 }
951 }
952
953 sendnoticetouser(proxyscannick,np,"Total %d scans actually found (%d active)",totalscansfound,activescansfound);
954 return CMD_OK;
955 }
956
957 void proxyscan_onconnect(int hooknum, void *arg) {
958 ps_ready = 1;
959
960 /* kick the queue.. */
961 startqueuedscans();
962 }
963
964 int proxyscandosave(void *sender, int cargc, char **cargv) {
965 nick *np = (nick *)sender;
966
967 sendnoticetouser(proxyscannick,np,"Saving cached hosts...");
968 dumpcachehosts(NULL);
969 sendnoticetouser(proxyscannick,np,"Done.");
970 return CMD_OK;
971 }
972
973 int proxyscandospew(void *sender, int cargc, char **cargv) {
974 nick *np = (nick *)sender;
975
976 if(cargc < 1)
977 return CMD_USAGE;
978
979 /* check our database for the ip supplied */
980 unsigned long a,b,c,d;
981 if (4 != sscanf(cargv[0],"%lu.%lu.%lu.%lu",&a,&b,&c,&d)) {
982 sendnoticetouser(proxyscannick,np,"Usage: spew x.x.x.x");
983 } else {
984 /* check db */
985 proxyscanspewip(proxyscannick,np,a,b,c,d);
986 }
987 return CMD_OK;
988 }
989
990 int proxyscandoshowkill(void *sender, int cargc, char **cargv) {
991 nick *np = (nick *)sender;
992
993 if(cargc < 1)
994 return CMD_USAGE;
995
996 /* check our database for the id supplied */
997 unsigned long a;
998 if (1 != sscanf(cargv[0],"%lu",&a)) {
999 sendnoticetouser(proxyscannick,np,"Usage: showkill <id>");
1000 } else {
1001 /* check db */
1002 proxyscanshowkill(proxyscannick,np,a);
1003 }
1004 return CMD_OK;
1005 }
1006
1007 void startnickscan(nick *np) {
1008 time_t t = time(NULL);
1009 int i;
1010 for(i=0;i<numscans;i++) {
1011 /* @@@TODO: we allow a forced scan to scan the same IP multiple times atm */
1012 queuescan(np->ipnode,thescans[i].type,thescans[i].port,SCLASS_NORMAL,t);
1013 }
1014 }
1015
1016 int proxyscandoscan(void *sender, int cargc, char **cargv) {
1017 nick *np = (nick *)sender;
1018 patricia_node_t *node;
1019 struct irc_in_addr sin;
1020 unsigned char bits;
1021 int i;
1022
1023 if(cargc < 1)
1024 return CMD_USAGE;
1025
1026 if (0 == ipmask_parse(cargv[0],&sin, &bits)) {
1027 sendnoticetouser(proxyscannick,np,"Usage: scan <ip>");
1028 } else {
1029 if (bits != 128 || !irc_in_addr_is_ipv4(&sin) || irc_in_addr_is_loopback(&sin)) {
1030 sendnoticetouser(proxyscannick,np,"You may only scan single IPv4 IP's");
1031 return CMD_OK;
1032 }
1033 if (bits != 128 || irc_in_addr_is_loopback(&sin)) {
1034 sendnoticetouser(proxyscannick,np,"You may only scan single IP's");
1035 return CMD_OK;
1036 }
1037
1038 time_t t;
1039 sendnoticetouser(proxyscannick,np,"Forcing scan of %s",IPtostr(sin));
1040 // * Just queue the scans directly here.. plonk them on the priority queue * /
1041 node = refnode(iptree, &sin, bits); /* node leaks node here - should only allow to scan a nick? */
1042 t = time(NULL);
1043 for(i=0;i<numscans;i++) {
1044 /* @@@TODO: we allow a forced scan to scan the same IP multiple times atm */
1045 queuescan(node,thescans[i].type,thescans[i].port,SCLASS_NORMAL,t);
1046 }
1047 }
1048 return CMD_OK;
1049 }
1050
1051 int proxyscandoscanfile(void *sender, int cargc, char **cargv) {
1052 nick *np = (nick *)sender;
1053 int i;
1054 time_t t = time(NULL);
1055 int pscantypes[PSCAN_MAXSCANS];
1056 int maxtypes;
1057 FILE *fp;
1058 int count;
1059
1060 if ((fp=fopen("data/doscan.txt","r"))==NULL) {
1061 sendnoticetouser(proxyscannick,np,"Unable to open file for reading!");
1062 return CMD_ERROR;
1063 }
1064
1065 {
1066 int *tscantypes;
1067 int maxno = -1;
1068
1069 for(i=0;i<numscans;i++)
1070 if(thescans[i].type > maxno)
1071 maxno = thescans[i].type;
1072
1073 tscantypes = malloc(sizeof(int) * maxno);
1074 for(i=0;i<maxno;i++)
1075 tscantypes[i] = 0;
1076
1077 for(i=0;i<numscans;i++)
1078 tscantypes[thescans[i].type] = 1;
1079
1080 for(i=0,maxtypes=0;i<maxno;i++)
1081 if(tscantypes[i])
1082 pscantypes[maxtypes++] = i;
1083
1084 free(tscantypes);
1085 }
1086
1087 count = 0;
1088 while (!feof(fp)) {
1089 patricia_node_t *node;
1090 struct irc_in_addr sin;
1091 unsigned char bits;
1092 unsigned short port;
1093 char buf[512], ip[512];
1094 int res;
1095
1096 fgets(buf,512,fp);
1097 if (feof(fp)) {
1098 break;
1099 }
1100
1101 res=sscanf(buf,"%s %hu",ip,&port);
1102
1103 if (res<2)
1104 continue;
1105
1106 if (0 == ipmask_parse(ip,&sin, &bits)) {
1107 /* invalid mask */
1108 } else {
1109 node = refnode(iptree, &sin, bits); /* LEAKS */
1110 if( node ) {
1111 for(i=0;i<maxtypes;i++) {
1112 queuescan(node,pscantypes[i],port,SCLASS_NORMAL,t);
1113 count++;
1114 }
1115 }
1116 }
1117 }
1118
1119 fclose(fp);
1120
1121 sendnoticetouser(proxyscannick,np,"Started %d scans...", count);
1122 return CMD_OK;
1123 }
1124
1125 int proxyscandoaddscan(void *sender, int cargc, char **cargv) {
1126 nick *np = (nick *)sender;
1127
1128 if(cargc < 1)
1129 return CMD_USAGE;
1130
1131 unsigned int a,b;
1132 if (sscanf(cargv[0],"%u %u",&a,&b) != 2) {
1133 sendnoticetouser(proxyscannick,np,"Usage: addscan <type> <port>");
1134 } else {
1135 sendnoticetouser(proxyscannick,np,"Added scan type %u port %u",a,b);
1136 proxyscan_addscantype(a,b);
1137 scanall(a,b);
1138 }
1139 return CMD_OK;
1140 }
1141
1142 int proxyscandodelscan(void *sender, int cargc, char **cargv) {
1143 nick *np = (nick *)sender;
1144
1145 if(cargc < 1)
1146 return CMD_USAGE;
1147
1148 unsigned int a,b;
1149 if (sscanf(cargv[0],"%u %u",&a,&b) != 2) {
1150 sendnoticetouser(proxyscannick,np,"Usage: delscan <type> <port>");
1151 } else {
1152 sendnoticetouser(proxyscannick,np,"Delete scan type %u port %u",a,b);
1153 proxyscan_delscantype(a,b);
1154 }
1155 return CMD_OK;
1156 }
1157
1158 int proxyscandoshowcommands(void *sender, int cargc, char **cargv) {
1159 nick *np = (nick *)sender;
1160 Command *cmdlist[100];
1161 int i,n;
1162
1163 n=getcommandlist(ps_commands,cmdlist,100);
1164
1165 sendnoticetouser(proxyscannick,np,"The following commands are registered at present:");
1166 for(i=0;i<n;i++) {
1167 sendnoticetouser(proxyscannick,np,"%s",cmdlist[i]->command->content);
1168 }
1169 sendnoticetouser(proxyscannick,np,"End of list.");
1170 return CMD_OK;
1171 }