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