]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/xline.cpp
5559390e73819c7442c4b259addc591ea6d08e05
[user/henk/code/inspircd.git] / src / xline.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  Inspire is copyright (C) 2002-2004 ChatSpike-Dev.
6  *                       E-mail:
7  *                <brain@chatspike.net>
8  *                <Craig@chatspike.net>
9  *     
10  * Written by Craig Edwards, Craig McLure, and others.
11  * This program is free but copyrighted software; see
12  *            the file COPYING for details.
13  *
14  * ---------------------------------------------------
15  */
16
17 #include "inspircd.h"
18 #include "inspircd_io.h"
19 #include "inspircd_util.h"
20 #include "inspircd_config.h"
21 #include <unistd.h>
22 #include <fcntl.h>
23 #include <sys/errno.h>
24 #include <sys/ioctl.h>
25 #include <sys/utsname.h>
26 #include <cstdio>
27 #include <time.h>
28 #include <string>
29 #ifdef GCC3
30 #include <ext/hash_map>
31 #else
32 #include <hash_map>
33 #endif
34 #include <map>
35 #include <sstream>
36 #include <vector>
37 #include <errno.h>
38 #include <deque>
39 #include <errno.h>
40 #include <unistd.h>
41 #include <sched.h>
42 #include "connection.h"
43 #include "users.h"
44 #include "servers.h"
45 #include "ctables.h"
46 #include "globals.h"
47 #include "modules.h"
48 #include "dynamic.h"
49 #include "wildcard.h"
50 #include "message.h"
51 #include "commands.h"
52 #include "xline.h"
53
54 #ifdef GCC3
55 #define nspace __gnu_cxx
56 #else
57 #define nspace std
58 #endif
59
60
61 using namespace std;
62
63 extern int MODCOUNT;
64 extern std::vector<Module*> modules;
65 extern std::vector<ircd_module*> factory;
66
67 extern int LogLevel;
68 extern char ServerName[MAXBUF];
69 extern char Network[MAXBUF];
70 extern char ServerDesc[MAXBUF];
71 extern char AdminName[MAXBUF];
72 extern char AdminEmail[MAXBUF];
73 extern char AdminNick[MAXBUF];
74 extern char diepass[MAXBUF];
75 extern char restartpass[MAXBUF];
76 extern char motd[MAXBUF];
77 extern char rules[MAXBUF];
78 extern char list[MAXBUF];
79 extern char PrefixQuit[MAXBUF];
80 extern char DieValue[MAXBUF];
81
82 extern int debugging;
83 extern int WHOWAS_STALE;
84 extern int WHOWAS_MAX;
85 extern int DieDelay;
86 extern time_t startup_time;
87 extern int NetBufferSize;
88 extern time_t nb_start;
89
90 extern std::vector<int> fd_reap;
91 extern std::vector<std::string> module_names;
92
93 extern int boundPortCount;
94 extern int portCount;
95 extern int UDPportCount;
96 extern int ports[MAXSOCKS];
97 extern int defaultRoute;
98
99 extern std::vector<long> auth_cookies;
100 extern std::stringstream config_f;
101
102 extern serverrec* me[32];
103
104 extern FILE *log_file;
105
106 namespace nspace
107 {
108 #ifdef GCC34
109         template<> struct hash<in_addr>
110 #else
111         template<> struct nspace::hash<in_addr>
112 #endif
113         {
114                 size_t operator()(const struct in_addr &a) const
115                 {
116                         size_t q;
117                         memcpy(&q,&a,sizeof(size_t));
118                         return q;
119                 }
120         };
121 #ifdef GCC34
122         template<> struct hash<string>
123 #else
124         template<> struct nspace::hash<string>
125 #endif
126         {
127                 size_t operator()(const string &s) const
128                 {
129                         char a[MAXBUF];
130                         static struct hash<const char *> strhash;
131                         strlcpy(a,s.c_str(),MAXBUF);
132                         strlower(a);
133                         return strhash(a);
134                 }
135         };
136 }       
137
138
139 struct StrHashComp
140 {
141
142         bool operator()(const string& s1, const string& s2) const
143         {
144                 char a[MAXBUF],b[MAXBUF];
145                 strlcpy(a,s1.c_str(),MAXBUF);
146                 strlcpy(b,s2.c_str(),MAXBUF);
147                 return (strcasecmp(a,b) == 0);
148         }
149
150 };
151
152 struct InAddr_HashComp
153 {
154
155         bool operator()(const in_addr &s1, const in_addr &s2) const
156         {
157                 size_t q;
158                 size_t p;
159                 
160                 memcpy(&q,&s1,sizeof(size_t));
161                 memcpy(&p,&s2,sizeof(size_t));
162                 
163                 return (q == p);
164         }
165
166 };
167
168
169 typedef nspace::hash_map<std::string, userrec*, nspace::hash<string>, StrHashComp> user_hash;
170 typedef nspace::hash_map<std::string, chanrec*, nspace::hash<string>, StrHashComp> chan_hash;
171 typedef nspace::hash_map<in_addr,string*, nspace::hash<in_addr>, InAddr_HashComp> address_cache;
172 typedef std::deque<command_t> command_table;
173
174
175 extern user_hash clientlist;
176 extern chan_hash chanlist;
177 extern user_hash whowas;
178 extern command_table cmdlist;
179 extern file_cache MOTD;
180 extern file_cache RULES;
181 extern address_cache IP;
182
183
184 std::vector<KLine> klines;
185 std::vector<GLine> glines;
186 std::vector<ZLine> zlines;
187 std::vector<QLine> qlines;
188
189 // Reads the default bans from the config file.
190 // only a very small number of bans are defined
191 // this way these days, such as qlines against 
192 // services nicks, etc.
193
194 void read_xline_defaults()
195 {
196         char ipmask[MAXBUF];
197         char nick[MAXBUF];
198         char host[MAXBUF];
199         char reason[MAXBUF];
200
201         for (int i = 0; i < ConfValueEnum("badip",&config_f); i++)
202         {
203                 ConfValue("badip","ipmask",i,ipmask,&config_f);
204                 ConfValue("badip","reason",i,reason,&config_f);
205                 add_zline(0,"<Config>",reason,ipmask);
206                 log(DEBUG,"Read Z line (badip tag): ipmask=%s reason=%s",ipmask,reason);
207         }
208         
209         for (int i = 0; i < ConfValueEnum("badnick",&config_f); i++)
210         {
211                 ConfValue("badnick","nick",i,nick,&config_f);
212                 ConfValue("badnick","reason",i,reason,&config_f);
213                 add_qline(0,"<Config>",reason,nick);
214                 log(DEBUG,"Read Q line (badnick tag): nick=%s reason=%s",nick,reason);
215         }
216         
217         for (int i = 0; i < ConfValueEnum("badhost",&config_f); i++)
218         {
219                 ConfValue("badhost","host",i,host,&config_f);
220                 ConfValue("badhost","reason",i,reason,&config_f);
221                 add_kline(0,"<Config>",reason,host);
222                 log(DEBUG,"Read K line (badhost tag): host=%s reason=%s",host,reason);
223         }
224 }
225
226 // adds a g:line
227
228 void add_gline(long duration, char* source, char* reason, char* hostmask)
229 {
230         del_gline(hostmask);
231         GLine item;
232         item.duration = duration;
233         strlcpy(item.hostmask,hostmask,MAXBUF);
234         strlcpy(item.reason,reason,MAXBUF);
235         strlcpy(item.source,source,MAXBUF);
236         item.n_matches = 0;
237         item.set_time = time(NULL);
238         glines.push_back(item);
239 }
240
241 // adds a q:line
242
243 void add_qline(long duration, char* source, char* reason, char* nickname)
244 {
245         del_qline(nickname);
246         QLine item;
247         item.duration = duration;
248         strlcpy(item.nick,nickname,MAXBUF);
249         strlcpy(item.reason,reason,MAXBUF);
250         strlcpy(item.source,source,MAXBUF);
251         item.n_matches = 0;
252         item.is_global = false;
253         item.set_time = time(NULL);
254         qlines.push_back(item);
255 }
256
257 // adds a z:line
258
259 void add_zline(long duration, char* source, char* reason, char* ipaddr)
260 {
261         del_zline(ipaddr);
262         ZLine item;
263         item.duration = duration;
264         strlcpy(item.ipaddr,ipaddr,MAXBUF);
265         strlcpy(item.reason,reason,MAXBUF);
266         strlcpy(item.source,source,MAXBUF);
267         item.n_matches = 0;
268         item.is_global = false;
269         item.set_time = time(NULL);
270         zlines.push_back(item);
271 }
272
273 // adds a k:line
274
275 void add_kline(long duration, char* source, char* reason, char* hostmask)
276 {
277         del_kline(hostmask);
278         KLine item;
279         item.duration = duration;
280         strlcpy(item.hostmask,hostmask,MAXBUF);
281         strlcpy(item.reason,reason,MAXBUF);
282         strlcpy(item.source,source,MAXBUF);
283         item.n_matches = 0;
284         item.set_time = time(NULL);
285         klines.push_back(item);
286 }
287
288 // deletes a g:line, returns true if the line existed and was removed
289
290 bool del_gline(char* hostmask)
291 {
292         for (std::vector<GLine>::iterator i = glines.begin(); i != glines.end(); i++)
293         {
294                 if (!strcasecmp(hostmask,i->hostmask))
295                 {
296                         glines.erase(i);
297                         return true;
298                 }
299         }
300         return false;
301 }
302
303 // deletes a q:line, returns true if the line existed and was removed
304
305 bool del_qline(char* nickname)
306 {
307         for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
308         {
309                 if (!strcasecmp(nickname,i->nick))
310                 {
311                         qlines.erase(i);
312                         return true;
313                 }
314         }
315         return false;
316 }
317
318 bool qline_make_global(char* nickname)
319 {
320         for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
321         {
322                 if (!strcasecmp(nickname,i->nick))
323                 {
324                         i->is_global = true;
325                         return true;
326                 }
327         }
328         return false;
329 }
330
331 bool zline_make_global(char* ipaddr)
332 {
333         for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
334         {
335                 if (!strcasecmp(ipaddr,i->ipaddr))
336                 {
337                         i->is_global = true;
338                         return true;
339                 }
340         }
341         return false;
342 }
343
344 void sync_xlines(serverrec* serv, char* tcp_host)
345 {
346         char data[MAXBUF];
347         
348         // for zlines and qlines, we should first check if theyre global...
349         for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
350         {
351                 if (i->is_global)
352                 {
353                         snprintf(data,MAXBUF,"} %s %s %ld %ld :%s",i->ipaddr,i->source,i->set_time,i->duration,i->reason);
354                         serv->SendPacket(data,tcp_host);
355                 }
356         }
357         for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
358         {
359                 if (i->is_global)
360                 {
361                         snprintf(data,MAXBUF,"{ %s %s %ld %ld :%s",i->nick,i->source,i->set_time,i->duration,i->reason);
362                         serv->SendPacket(data,tcp_host);
363                 }
364         }
365         // glines are always global, so no need to check
366         for (std::vector<GLine>::iterator i = glines.begin(); i != glines.end(); i++)
367         {
368                 snprintf(data,MAXBUF,"# %s %s %ld %ld :%s",i->hostmask,i->source,i->set_time,i->duration,i->reason);
369                 serv->SendPacket(data,tcp_host);
370         }
371 }
372
373
374 // deletes a z:line, returns true if the line existed and was removed
375
376 bool del_zline(char* ipaddr)
377 {
378         for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
379         {
380                 if (!strcasecmp(ipaddr,i->ipaddr))
381                 {
382                         zlines.erase(i);
383                         return true;
384                 }
385         }
386         return false;
387 }
388
389 // deletes a k:line, returns true if the line existed and was removed
390
391 bool del_kline(char* hostmask)
392 {
393         for (std::vector<KLine>::iterator i = klines.begin(); i != klines.end(); i++)
394         {
395                 if (!strcasecmp(hostmask,i->hostmask))
396                 {
397                         klines.erase(i);
398                         return true;
399                 }
400         }
401         return false;
402 }
403
404 // returns a pointer to the reason if a nickname matches a qline, NULL if it didnt match
405
406 char* matches_qline(const char* nick)
407 {
408         for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
409         {
410                 if (match(nick,i->nick))
411                 {
412                         return i->reason;
413                 }
414         }
415         return NULL;
416 }
417
418 // returns a pointer to the reason if a host matches a gline, NULL if it didnt match
419
420 char* matches_gline(const char* host)
421 {
422         for (std::vector<GLine>::iterator i = glines.begin(); i != glines.end(); i++)
423         {
424                 if (match(host,i->hostmask))
425                 {
426                         return i->reason;
427                 }
428         }
429         return NULL;
430 }
431
432 void gline_set_creation_time(char* host, time_t create_time)
433 {
434         for (std::vector<GLine>::iterator i = glines.begin(); i != glines.end(); i++)
435         {
436                 if (!strcasecmp(host,i->hostmask))
437                 {
438                         i->set_time = create_time;
439                         return;
440                 }
441         }
442         return ;        
443 }
444
445 void qline_set_creation_time(char* nick, time_t create_time)
446 {
447         for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
448         {
449                 if (!strcasecmp(nick,i->nick))
450                 {
451                         i->set_time = create_time;
452                         return;
453                 }
454         }
455         return ;        
456 }
457
458 void zline_set_creation_time(char* ip, time_t create_time)
459 {
460         for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
461         {
462                 if (!strcasecmp(ip,i->ipaddr))
463                 {
464                         i->set_time = create_time;
465                         return;
466                 }
467         }
468         return ;        
469 }
470
471 // returns a pointer to the reason if an ip address matches a zline, NULL if it didnt match
472
473 char* matches_zline(const char* ipaddr)
474 {
475         for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
476         {
477                 if (match(ipaddr,i->ipaddr))
478                 {
479                         return i->reason;
480                 }
481         }
482         return NULL;
483 }
484
485 // returns a pointer to the reason if a host matches a kline, NULL if it didnt match
486
487 char* matches_kline(const char* host)
488 {
489         for (std::vector<KLine>::iterator i = klines.begin(); i != klines.end(); i++)
490         {
491                 if (match(host,i->hostmask))
492                 {
493                         return i->reason;
494                 }
495         }
496         return NULL;
497 }
498
499 // removes lines that have expired
500
501 void expire_lines()
502 {
503         bool go_again = true;
504         time_t current = time(NULL);
505         
506         // because we mess up an iterator when we remove from the vector, we must bail from
507         // the loop early if we delete an item, therefore this outer while loop is required.
508         while (go_again)
509         {
510                 go_again = false;
511
512                 for (std::vector<KLine>::iterator i = klines.begin(); i != klines.end(); i++)
513                 {
514                         if ((current > (i->duration + i->set_time)) && (i->duration > 0))
515                         {
516                                 WriteOpers("Expiring timed K-Line %s (set by %s %d seconds ago)",i->hostmask,i->source,i->duration);
517                                 klines.erase(i);
518                                 go_again = true;
519                                 break;
520                         }
521                 }
522
523                 for (std::vector<GLine>::iterator i = glines.begin(); i != glines.end(); i++)
524                 {
525                         if ((current > (i->duration + i->set_time)) && (i->duration > 0))
526                         {
527                                 WriteOpers("Expiring timed G-Line %s (set by %s %d seconds ago)",i->hostmask,i->source,i->duration);
528                                 glines.erase(i);
529                                 go_again = true;
530                                 break;
531                         }
532                 }
533
534                 for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
535                 {
536                         if ((current > (i->duration + i->set_time)) && (i->duration > 0))
537                         {
538                                 WriteOpers("Expiring timed Z-Line %s (set by %s %d seconds ago)",i->ipaddr,i->source,i->duration);
539                                 zlines.erase(i);
540                                 go_again = true;
541                                 break;
542                         }
543                 }
544
545                 for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
546                 {
547                         if ((current > (i->duration + i->set_time)) && (i->duration > 0))
548                         {
549                                 WriteOpers("Expiring timed Q-Line %s (set by %s %d seconds ago)",i->nick,i->source,i->duration);
550                                 qlines.erase(i);
551                                 go_again = true;
552                                 break;
553                         }
554                 }
555         }
556 }
557
558 // applies lines, removing clients and changing nicks etc as applicable
559
560 void apply_lines()
561 {
562         bool go_again = true;
563         char reason[MAXBUF];
564         char host[MAXBUF];
565         
566         if ((!glines.size()) && (!klines.size()) && (!zlines.size()) && (!qlines.size()))
567                 return;
568         
569         while (go_again)
570         {
571                 go_again = false;
572                 for (user_hash::const_iterator u = clientlist.begin(); u != clientlist.end(); u++)
573                 {
574                         if (!strcasecmp(u->second->server,ServerName))
575                         {
576                                 snprintf(host,MAXBUF,"%s@%s",u->second->ident,u->second->host);
577                                 if (glines.size())
578                                 {
579                                         char* check = matches_gline(host);
580                                         if (check)
581                                         {
582                                                 WriteOpers("*** User %s matches G-Line: %s",u->second->nick,check);
583                                                 snprintf(reason,MAXBUF,"G-Lined: %s",check);
584                                                 kill_link(u->second,reason);
585                                                 go_again = true;
586                                                 break;
587                                         }
588                                 }
589                                 if (klines.size())
590                                 {
591                                         char* check = matches_kline(host);
592                                         if (check)
593                                         {
594                                                 WriteOpers("*** User %s matches K-Line: %s",u->second->nick,check);
595                                                 snprintf(reason,MAXBUF,"K-Lined: %s",check);
596                                                 kill_link(u->second,reason);
597                                                 go_again = true;
598                                                 break;
599                                         }
600                                 }
601                                 if (qlines.size())
602                                 {
603                                         char* check = matches_qline(u->second->nick);
604                                         if (check)
605                                         {
606                                                 snprintf(reason,MAXBUF,"Matched Q-Lined nick: %s",check);
607                                                 WriteOpers("*** Q-Lined nickname %s from %s: %s",u->second->nick,u->second->host,check);
608                                                 kill_link(u->second,reason);
609                                                 go_again = true;
610                                                 break;
611                                         }
612                                 }
613                                 if (zlines.size())
614                                 {
615                                         char* check = matches_zline(u->second->ip);
616                                         if (check)
617                                         {
618                                                 snprintf(reason,MAXBUF,"Z-Lined: %s",check);
619                                                 WriteOpers("*** User %s matches Z-Line: %s",u->second->nick,u->second->host,check);
620                                                 kill_link(u->second,reason);
621                                                 go_again = true;
622                                                 break;
623                                         }
624                                 }
625                         }
626                 }
627         }
628 }
629
630 void stats_k(userrec* user)
631 {
632         for (std::vector<KLine>::iterator i = klines.begin(); i != klines.end(); i++)
633         {
634                 WriteServ(user->fd,"216 %s :%s %d %d %s %s",user->nick,i->hostmask,i->set_time,i->duration,i->source,i->reason);
635         }
636 }
637
638 void stats_g(userrec* user)
639 {
640         for (std::vector<GLine>::iterator i = glines.begin(); i != glines.end(); i++)
641         {
642                 WriteServ(user->fd,"223 %s :%s %d %d %s %s",user->nick,i->hostmask,i->set_time,i->duration,i->source,i->reason);
643         }
644 }
645
646 void stats_q(userrec* user)
647 {
648         for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
649         {
650                 WriteServ(user->fd,"217 %s :%s %d %d %s %s",user->nick,i->nick,i->set_time,i->duration,i->source,i->reason);
651         }
652 }
653
654 void stats_z(userrec* user)
655 {
656         for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
657         {
658                 WriteServ(user->fd,"223 %s :%s %d %d %s %s",user->nick,i->ipaddr,i->set_time,i->duration,i->source,i->reason);
659         }
660 }
661
662
663