]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/xline.cpp
Changed occurances of vector to std::vector
[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         template<> struct nspace::hash<in_addr>
109         {
110                 size_t operator()(const struct in_addr &a) const
111                 {
112                         size_t q;
113                         memcpy(&q,&a,sizeof(size_t));
114                         return q;
115                 }
116         };
117
118         template<> struct nspace::hash<string>
119         {
120                 size_t operator()(const string &s) const
121                 {
122                         char a[MAXBUF];
123                         static struct hash<const char *> strhash;
124                         strlcpy(a,s.c_str(),MAXBUF);
125                         strlower(a);
126                         return strhash(a);
127                 }
128         };
129 }       
130
131
132 struct StrHashComp
133 {
134
135         bool operator()(const string& s1, const string& s2) const
136         {
137                 char a[MAXBUF],b[MAXBUF];
138                 strlcpy(a,s1.c_str(),MAXBUF);
139                 strlcpy(b,s2.c_str(),MAXBUF);
140                 return (strcasecmp(a,b) == 0);
141         }
142
143 };
144
145 struct InAddr_HashComp
146 {
147
148         bool operator()(const in_addr &s1, const in_addr &s2) const
149         {
150                 size_t q;
151                 size_t p;
152                 
153                 memcpy(&q,&s1,sizeof(size_t));
154                 memcpy(&p,&s2,sizeof(size_t));
155                 
156                 return (q == p);
157         }
158
159 };
160
161
162 typedef nspace::hash_map<std::string, userrec*, nspace::hash<string>, StrHashComp> user_hash;
163 typedef nspace::hash_map<std::string, chanrec*, nspace::hash<string>, StrHashComp> chan_hash;
164 typedef nspace::hash_map<in_addr,string*, nspace::hash<in_addr>, InAddr_HashComp> address_cache;
165 typedef std::deque<command_t> command_table;
166
167
168 extern user_hash clientlist;
169 extern chan_hash chanlist;
170 extern user_hash whowas;
171 extern command_table cmdlist;
172 extern file_cache MOTD;
173 extern file_cache RULES;
174 extern address_cache IP;
175
176
177 std::vector<KLine> klines;
178 std::vector<GLine> glines;
179 std::vector<ZLine> zlines;
180 std::vector<QLine> qlines;
181
182 // Reads the default bans from the config file.
183 // only a very small number of bans are defined
184 // this way these days, such as qlines against 
185 // services nicks, etc.
186
187 void read_xline_defaults()
188 {
189         char ipmask[MAXBUF];
190         char nick[MAXBUF];
191         char host[MAXBUF];
192         char reason[MAXBUF];
193
194         for (int i = 0; i < ConfValueEnum("badip",&config_f); i++)
195         {
196                 ConfValue("badip","ipmask",i,ipmask,&config_f);
197                 ConfValue("badip","reason",i,reason,&config_f);
198                 add_zline(0,"<Config>",reason,ipmask);
199                 log(DEBUG,"Read Z line (badip tag): ipmask=%s reason=%s",ipmask,reason);
200         }
201         
202         for (int i = 0; i < ConfValueEnum("badnick",&config_f); i++)
203         {
204                 ConfValue("badnick","nick",i,nick,&config_f);
205                 ConfValue("badnick","reason",i,reason,&config_f);
206                 add_qline(0,"<Config>",reason,nick);
207                 log(DEBUG,"Read Q line (badnick tag): nick=%s reason=%s",nick,reason);
208         }
209         
210         for (int i = 0; i < ConfValueEnum("badhost",&config_f); i++)
211         {
212                 ConfValue("badhost","host",i,host,&config_f);
213                 ConfValue("badhost","reason",i,reason,&config_f);
214                 add_kline(0,"<Config>",reason,host);
215                 log(DEBUG,"Read K line (badhost tag): host=%s reason=%s",host,reason);
216         }
217 }
218
219 // adds a g:line
220
221 void add_gline(long duration, char* source, char* reason, char* hostmask)
222 {
223         del_gline(hostmask);
224         GLine item;
225         item.duration = duration;
226         strlcpy(item.hostmask,hostmask,MAXBUF);
227         strlcpy(item.reason,reason,MAXBUF);
228         strlcpy(item.source,source,MAXBUF);
229         item.n_matches = 0;
230         item.set_time = time(NULL);
231         glines.push_back(item);
232 }
233
234 // adds a q:line
235
236 void add_qline(long duration, char* source, char* reason, char* nickname)
237 {
238         del_qline(nickname);
239         QLine item;
240         item.duration = duration;
241         strlcpy(item.nick,nickname,MAXBUF);
242         strlcpy(item.reason,reason,MAXBUF);
243         strlcpy(item.source,source,MAXBUF);
244         item.n_matches = 0;
245         item.is_global = false;
246         item.set_time = time(NULL);
247         qlines.push_back(item);
248 }
249
250 // adds a z:line
251
252 void add_zline(long duration, char* source, char* reason, char* ipaddr)
253 {
254         del_zline(ipaddr);
255         ZLine item;
256         item.duration = duration;
257         strlcpy(item.ipaddr,ipaddr,MAXBUF);
258         strlcpy(item.reason,reason,MAXBUF);
259         strlcpy(item.source,source,MAXBUF);
260         item.n_matches = 0;
261         item.is_global = false;
262         item.set_time = time(NULL);
263         zlines.push_back(item);
264 }
265
266 // adds a k:line
267
268 void add_kline(long duration, char* source, char* reason, char* hostmask)
269 {
270         del_kline(hostmask);
271         KLine item;
272         item.duration = duration;
273         strlcpy(item.hostmask,hostmask,MAXBUF);
274         strlcpy(item.reason,reason,MAXBUF);
275         strlcpy(item.source,source,MAXBUF);
276         item.n_matches = 0;
277         item.set_time = time(NULL);
278         klines.push_back(item);
279 }
280
281 // deletes a g:line, returns true if the line existed and was removed
282
283 bool del_gline(char* hostmask)
284 {
285         for (std::vector<GLine>::iterator i = glines.begin(); i != glines.end(); i++)
286         {
287                 if (!strcasecmp(hostmask,i->hostmask))
288                 {
289                         glines.erase(i);
290                         return true;
291                 }
292         }
293         return false;
294 }
295
296 // deletes a q:line, returns true if the line existed and was removed
297
298 bool del_qline(char* nickname)
299 {
300         for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
301         {
302                 if (!strcasecmp(nickname,i->nick))
303                 {
304                         qlines.erase(i);
305                         return true;
306                 }
307         }
308         return false;
309 }
310
311 bool qline_make_global(char* nickname)
312 {
313         for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
314         {
315                 if (!strcasecmp(nickname,i->nick))
316                 {
317                         i->is_global = true;
318                         return true;
319                 }
320         }
321         return false;
322 }
323
324 bool zline_make_global(char* ipaddr)
325 {
326         for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
327         {
328                 if (!strcasecmp(ipaddr,i->ipaddr))
329                 {
330                         i->is_global = true;
331                         return true;
332                 }
333         }
334         return false;
335 }
336
337 void sync_xlines(serverrec* serv, char* tcp_host)
338 {
339         char data[MAXBUF];
340         
341         // for zlines and qlines, we should first check if theyre global...
342         for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
343         {
344                 if (i->is_global)
345                 {
346                         snprintf(data,MAXBUF,"} %s %s %ld %ld :%s",i->ipaddr,i->source,i->set_time,i->duration,i->reason);
347                         serv->SendPacket(data,tcp_host);
348                 }
349         }
350         for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
351         {
352                 if (i->is_global)
353                 {
354                         snprintf(data,MAXBUF,"{ %s %s %ld %ld :%s",i->nick,i->source,i->set_time,i->duration,i->reason);
355                         serv->SendPacket(data,tcp_host);
356                 }
357         }
358         // glines are always global, so no need to check
359         for (std::vector<GLine>::iterator i = glines.begin(); i != glines.end(); i++)
360         {
361                 snprintf(data,MAXBUF,"# %s %s %ld %ld :%s",i->hostmask,i->source,i->set_time,i->duration,i->reason);
362                 serv->SendPacket(data,tcp_host);
363         }
364 }
365
366
367 // deletes a z:line, returns true if the line existed and was removed
368
369 bool del_zline(char* ipaddr)
370 {
371         for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
372         {
373                 if (!strcasecmp(ipaddr,i->ipaddr))
374                 {
375                         zlines.erase(i);
376                         return true;
377                 }
378         }
379         return false;
380 }
381
382 // deletes a k:line, returns true if the line existed and was removed
383
384 bool del_kline(char* hostmask)
385 {
386         for (std::vector<KLine>::iterator i = klines.begin(); i != klines.end(); i++)
387         {
388                 if (!strcasecmp(hostmask,i->hostmask))
389                 {
390                         klines.erase(i);
391                         return true;
392                 }
393         }
394         return false;
395 }
396
397 // returns a pointer to the reason if a nickname matches a qline, NULL if it didnt match
398
399 char* matches_qline(const char* nick)
400 {
401         for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
402         {
403                 if (match(nick,i->nick))
404                 {
405                         return i->reason;
406                 }
407         }
408         return NULL;
409 }
410
411 // returns a pointer to the reason if a host matches a gline, NULL if it didnt match
412
413 char* matches_gline(const char* host)
414 {
415         for (std::vector<GLine>::iterator i = glines.begin(); i != glines.end(); i++)
416         {
417                 if (match(host,i->hostmask))
418                 {
419                         return i->reason;
420                 }
421         }
422         return NULL;
423 }
424
425 void gline_set_creation_time(char* host, time_t create_time)
426 {
427         for (std::vector<GLine>::iterator i = glines.begin(); i != glines.end(); i++)
428         {
429                 if (!strcasecmp(host,i->hostmask))
430                 {
431                         i->set_time = create_time;
432                         return;
433                 }
434         }
435         return ;        
436 }
437
438 void qline_set_creation_time(char* nick, time_t create_time)
439 {
440         for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
441         {
442                 if (!strcasecmp(nick,i->nick))
443                 {
444                         i->set_time = create_time;
445                         return;
446                 }
447         }
448         return ;        
449 }
450
451 void zline_set_creation_time(char* ip, time_t create_time)
452 {
453         for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
454         {
455                 if (!strcasecmp(ip,i->ipaddr))
456                 {
457                         i->set_time = create_time;
458                         return;
459                 }
460         }
461         return ;        
462 }
463
464 // returns a pointer to the reason if an ip address matches a zline, NULL if it didnt match
465
466 char* matches_zline(const char* ipaddr)
467 {
468         for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
469         {
470                 if (match(ipaddr,i->ipaddr))
471                 {
472                         return i->reason;
473                 }
474         }
475         return NULL;
476 }
477
478 // returns a pointer to the reason if a host matches a kline, NULL if it didnt match
479
480 char* matches_kline(const char* host)
481 {
482         for (std::vector<KLine>::iterator i = klines.begin(); i != klines.end(); i++)
483         {
484                 if (match(host,i->hostmask))
485                 {
486                         return i->reason;
487                 }
488         }
489         return NULL;
490 }
491
492 // removes lines that have expired
493
494 void expire_lines()
495 {
496         bool go_again = true;
497         time_t current = time(NULL);
498         
499         // because we mess up an iterator when we remove from the vector, we must bail from
500         // the loop early if we delete an item, therefore this outer while loop is required.
501         while (go_again)
502         {
503                 go_again = false;
504
505                 for (std::vector<KLine>::iterator i = klines.begin(); i != klines.end(); i++)
506                 {
507                         if ((current > (i->duration + i->set_time)) && (i->duration > 0))
508                         {
509                                 WriteOpers("Expiring timed K-Line %s (set by %s %d seconds ago)",i->hostmask,i->source,i->duration);
510                                 klines.erase(i);
511                                 go_again = true;
512                                 break;
513                         }
514                 }
515
516                 for (std::vector<GLine>::iterator i = glines.begin(); i != glines.end(); i++)
517                 {
518                         if ((current > (i->duration + i->set_time)) && (i->duration > 0))
519                         {
520                                 WriteOpers("Expiring timed G-Line %s (set by %s %d seconds ago)",i->hostmask,i->source,i->duration);
521                                 glines.erase(i);
522                                 go_again = true;
523                                 break;
524                         }
525                 }
526
527                 for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
528                 {
529                         if ((current > (i->duration + i->set_time)) && (i->duration > 0))
530                         {
531                                 WriteOpers("Expiring timed Z-Line %s (set by %s %d seconds ago)",i->ipaddr,i->source,i->duration);
532                                 zlines.erase(i);
533                                 go_again = true;
534                                 break;
535                         }
536                 }
537
538                 for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
539                 {
540                         if ((current > (i->duration + i->set_time)) && (i->duration > 0))
541                         {
542                                 WriteOpers("Expiring timed Q-Line %s (set by %s %d seconds ago)",i->nick,i->source,i->duration);
543                                 qlines.erase(i);
544                                 go_again = true;
545                                 break;
546                         }
547                 }
548         }
549 }
550
551 // applies lines, removing clients and changing nicks etc as applicable
552
553 void apply_lines()
554 {
555         bool go_again = true;
556         char reason[MAXBUF];
557         char host[MAXBUF];
558         
559         if ((!glines.size()) && (!klines.size()) && (!zlines.size()) && (!qlines.size()))
560                 return;
561         
562         while (go_again)
563         {
564                 go_again = false;
565                 for (user_hash::const_iterator u = clientlist.begin(); u != clientlist.end(); u++)
566                 {
567                         if (!strcasecmp(u->second->server,ServerName))
568                         {
569                                 snprintf(host,MAXBUF,"%s@%s",u->second->ident,u->second->host);
570                                 if (glines.size())
571                                 {
572                                         char* check = matches_gline(host);
573                                         if (check)
574                                         {
575                                                 WriteOpers("*** User %s matches G-Line: %s",u->second->nick,check);
576                                                 snprintf(reason,MAXBUF,"G-Lined: %s",check);
577                                                 kill_link(u->second,reason);
578                                                 go_again = true;
579                                                 break;
580                                         }
581                                 }
582                                 if (klines.size())
583                                 {
584                                         char* check = matches_kline(host);
585                                         if (check)
586                                         {
587                                                 WriteOpers("*** User %s matches K-Line: %s",u->second->nick,check);
588                                                 snprintf(reason,MAXBUF,"K-Lined: %s",check);
589                                                 kill_link(u->second,reason);
590                                                 go_again = true;
591                                                 break;
592                                         }
593                                 }
594                                 if (qlines.size())
595                                 {
596                                         char* check = matches_qline(u->second->nick);
597                                         if (check)
598                                         {
599                                                 snprintf(reason,MAXBUF,"Matched Q-Lined nick: %s",check);
600                                                 WriteOpers("*** Q-Lined nickname %s from %s: %s",u->second->nick,u->second->host,check);
601                                                 kill_link(u->second,reason);
602                                                 go_again = true;
603                                                 break;
604                                         }
605                                 }
606                                 if (zlines.size())
607                                 {
608                                         char* check = matches_zline(u->second->ip);
609                                         if (check)
610                                         {
611                                                 snprintf(reason,MAXBUF,"Z-Lined: %s",check);
612                                                 WriteOpers("*** User %s matches Z-Line: %s",u->second->nick,u->second->host,check);
613                                                 kill_link(u->second,reason);
614                                                 go_again = true;
615                                                 break;
616                                         }
617                                 }
618                         }
619                 }
620         }
621 }
622
623 void stats_k(userrec* user)
624 {
625         for (std::vector<KLine>::iterator i = klines.begin(); i != klines.end(); i++)
626         {
627                 WriteServ(user->fd,"216 %s :%s %d %d %s %s",user->nick,i->hostmask,i->set_time,i->duration,i->source,i->reason);
628         }
629 }
630
631 void stats_g(userrec* user)
632 {
633         for (std::vector<GLine>::iterator i = glines.begin(); i != glines.end(); i++)
634         {
635                 WriteServ(user->fd,"223 %s :%s %d %d %s %s",user->nick,i->hostmask,i->set_time,i->duration,i->source,i->reason);
636         }
637 }
638
639 void stats_q(userrec* user)
640 {
641         for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
642         {
643                 WriteServ(user->fd,"217 %s :%s %d %d %s %s",user->nick,i->nick,i->set_time,i->duration,i->source,i->reason);
644         }
645 }
646
647 void stats_z(userrec* user)
648 {
649         for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
650         {
651                 WriteServ(user->fd,"223 %s :%s %d %d %s %s",user->nick,i->ipaddr,i->set_time,i->duration,i->source,i->reason);
652         }
653 }
654
655
656