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