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