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