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