]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/xline.cpp
Fixed minor typos
[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.is_global = false;
231         item.set_time = time(NULL);
232         qlines.push_back(item);
233 }
234
235 // adds a z:line
236
237 void add_zline(long duration, char* source, char* reason, char* ipaddr)
238 {
239         del_zline(ipaddr);
240         ZLine item;
241         item.duration = duration;
242         strncpy(item.ipaddr,ipaddr,MAXBUF);
243         strncpy(item.reason,reason,MAXBUF);
244         strncpy(item.source,source,MAXBUF);
245         item.n_matches = 0;
246         item.is_global = false;
247         item.set_time = time(NULL);
248         zlines.push_back(item);
249 }
250
251 // adds a k:line
252
253 void add_kline(long duration, char* source, char* reason, char* hostmask)
254 {
255         del_kline(hostmask);
256         KLine item;
257         item.duration = duration;
258         strncpy(item.hostmask,hostmask,MAXBUF);
259         strncpy(item.reason,reason,MAXBUF);
260         strncpy(item.source,source,MAXBUF);
261         item.n_matches = 0;
262         item.set_time = time(NULL);
263         klines.push_back(item);
264 }
265
266 // deletes a g:line, returns true if the line existed and was removed
267
268 bool del_gline(char* hostmask)
269 {
270         for (std::vector<GLine>::iterator i = glines.begin(); i != glines.end(); i++)
271         {
272                 if (!strcasecmp(hostmask,i->hostmask))
273                 {
274                         glines.erase(i);
275                         return true;
276                 }
277         }
278         return false;
279 }
280
281 // deletes a q:line, returns true if the line existed and was removed
282
283 bool del_qline(char* nickname)
284 {
285         for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
286         {
287                 if (!strcasecmp(nickname,i->nick))
288                 {
289                         qlines.erase(i);
290                         return true;
291                 }
292         }
293         return false;
294 }
295
296 bool qline_make_global(char* nickname)
297 {
298         for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
299         {
300                 if (!strcasecmp(nickname,i->nick))
301                 {
302                         i->is_global = true;
303                         return true;
304                 }
305         }
306         return false;
307 }
308
309 bool zline_make_global(char* ipaddr)
310 {
311         for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
312         {
313                 if (!strcasecmp(ipaddr,i->ipaddr))
314                 {
315                         i->is_global = true;
316                         return true;
317                 }
318         }
319         return false;
320 }
321
322 void sync_xlines(serverrec* serv, char* tcp_host)
323 {
324         char data[MAXBUF];
325         
326         // for zlines and qlines, we should first check if theyre global...
327         for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
328         {
329                 if (i->is_global)
330                 {
331                         snprintf(data,MAXBUF,"} %s %s %ld %ld :%s",i->ipaddr,i->source,i->set_time,i->duration,i->reason);
332                         serv->SendPacket(data,tcp_host);
333                 }
334         }
335         for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
336         {
337                 if (i->is_global)
338                 {
339                         snprintf(data,MAXBUF,"{ %s %s %ld %ld :%s",i->ipaddr,i->source,i->set_time,i->duration,i->reason);
340                         serv->SendPacket(data,tcp_host);
341                 }
342         }
343         // glines are always global, so no need to check
344         for (std::vector<GLine>::iterator i = glines.begin(); i != glines.end(); i++)
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
351
352 // deletes a z:line, returns true if the line existed and was removed
353
354 bool del_zline(char* ipaddr)
355 {
356         for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
357         {
358                 if (!strcasecmp(ipaddr,i->ipaddr))
359                 {
360                         zlines.erase(i);
361                         return true;
362                 }
363         }
364         return false;
365 }
366
367 // deletes a k:line, returns true if the line existed and was removed
368
369 bool del_kline(char* hostmask)
370 {
371         for (std::vector<KLine>::iterator i = klines.begin(); i != klines.end(); i++)
372         {
373                 if (!strcasecmp(hostmask,i->hostmask))
374                 {
375                         klines.erase(i);
376                         return true;
377                 }
378         }
379         return false;
380 }
381
382 // returns a pointer to the reason if a nickname matches a qline, NULL if it didnt match
383
384 char* matches_qline(const char* nick)
385 {
386         for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
387         {
388                 if (match(nick,i->nick))
389                 {
390                         return i->reason;
391                 }
392         }
393         return NULL;
394 }
395
396 // returns a pointer to the reason if a host matches a gline, NULL if it didnt match
397
398 char* matches_gline(const char* host)
399 {
400         for (std::vector<GLine>::iterator i = glines.begin(); i != glines.end(); i++)
401         {
402                 if (match(host,i->hostmask))
403                 {
404                         return i->reason;
405                 }
406         }
407         return NULL;
408 }
409
410 void gline_set_creation_time(char* host, time_t create_time)
411 {
412         for (std::vector<GLine>::iterator i = glines.begin(); i != glines.end(); i++)
413         {
414                 if (!strcasecmp(host,i->hostmask))
415                 {
416                         i->set_time = create_time;
417                         return;
418                 }
419         }
420         return ;        
421 }
422
423 void qline_set_creation_time(char* nick, time_t create_time)
424 {
425         for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
426         {
427                 if (!strcasecmp(nick,i->nick))
428                 {
429                         i->set_time = create_time;
430                         return;
431                 }
432         }
433         return ;        
434 }
435
436 void zline_set_creation_time(char* ip, time_t create_time)
437 {
438         for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
439         {
440                 if (!strcasecmp(ip,i->ipaddr))
441                 {
442                         i->set_time = create_time;
443                         return;
444                 }
445         }
446         return ;        
447 }
448
449 // returns a pointer to the reason if an ip address matches a zline, NULL if it didnt match
450
451 char* matches_zline(const char* ipaddr)
452 {
453         for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
454         {
455                 if (match(ipaddr,i->ipaddr))
456                 {
457                         return i->reason;
458                 }
459         }
460         return NULL;
461 }
462
463 // returns a pointer to the reason if a host matches a kline, NULL if it didnt match
464
465 char* matches_kline(const char* host)
466 {
467         for (std::vector<KLine>::iterator i = klines.begin(); i != klines.end(); i++)
468         {
469                 if (match(host,i->hostmask))
470                 {
471                         return i->reason;
472                 }
473         }
474         return NULL;
475 }
476
477 // removes lines that have expired
478
479 void expire_lines()
480 {
481         bool go_again = true;
482         time_t current = time(NULL);
483         
484         // because we mess up an iterator when we remove from the vector, we must bail from
485         // the loop early if we delete an item, therefore this outer while loop is required.
486         while (go_again)
487         {
488                 go_again = false;
489
490                 for (std::vector<KLine>::iterator i = klines.begin(); i != klines.end(); i++)
491                 {
492                         if ((current > (i->duration + i->set_time)) && (i->duration > 0))
493                         {
494                                 WriteOpers("Expiring timed K-Line %s (set by %s %d seconds ago)",i->hostmask,i->source,i->duration);
495                                 klines.erase(i);
496                                 go_again = true;
497                                 break;
498                         }
499                 }
500
501                 for (std::vector<GLine>::iterator i = glines.begin(); i != glines.end(); i++)
502                 {
503                         if ((current > (i->duration + i->set_time)) && (i->duration > 0))
504                         {
505                                 WriteOpers("Expiring timed G-Line %s (set by %s %d seconds ago)",i->hostmask,i->source,i->duration);
506                                 glines.erase(i);
507                                 go_again = true;
508                                 break;
509                         }
510                 }
511
512                 for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
513                 {
514                         if ((current > (i->duration + i->set_time)) && (i->duration > 0))
515                         {
516                                 WriteOpers("Expiring timed Z-Line %s (set by %s %d seconds ago)",i->ipaddr,i->source,i->duration);
517                                 zlines.erase(i);
518                                 go_again = true;
519                                 break;
520                         }
521                 }
522
523                 for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
524                 {
525                         if ((current > (i->duration + i->set_time)) && (i->duration > 0))
526                         {
527                                 WriteOpers("Expiring timed Q-Line %s (set by %s %d seconds ago)",i->nick,i->source,i->duration);
528                                 qlines.erase(i);
529                                 go_again = true;
530                                 break;
531                         }
532                 }
533         }
534 }
535
536 // applies lines, removing clients and changing nicks etc as applicable
537
538 void apply_lines()
539 {
540         bool go_again = true;
541         char reason[MAXBUF];
542         char host[MAXBUF];
543         
544         while (go_again)
545         {
546                 go_again = false;
547                 for (user_hash::const_iterator u = clientlist.begin(); u != clientlist.end(); u++)
548                 {
549                         if (!strcasecmp(u->second->server,ServerName))
550                         {
551                                 snprintf(host,MAXBUF,"%s@%s",u->second->ident,u->second->host);
552                                 char* check = matches_gline(host);
553                                 if (check)
554                                 {
555                                         WriteOpers("*** User %s matches G-Line: %s",u->second->nick,check);
556                                         snprintf(reason,MAXBUF,"G-Lined: %s",check);
557                                         kill_link(u->second,reason);
558                                         go_again = true;
559                                         break;
560                                 }
561                         }
562                 }
563
564                 for (user_hash::const_iterator u = clientlist.begin(); u != clientlist.end(); u++)
565                 {
566                         if (!strcasecmp(u->second->server,ServerName))
567                         {
568                                 snprintf(host,MAXBUF,"%s@%s",u->second->ident,u->second->host);
569                                 char* check = matches_kline(host);
570                                 if (check)
571                                 {
572                                         WriteOpers("*** User %s matches K-Line: %s",u->second->nick,check);
573                                         snprintf(reason,MAXBUF,"K-Lined: %s",check);
574                                         kill_link(u->second,reason);
575                                         go_again = true;
576                                         break;
577                                 }
578                         }
579                 }
580
581                 for (user_hash::const_iterator u = clientlist.begin(); u != clientlist.end(); u++)
582                 {
583                         if (!strcasecmp(u->second->server,ServerName))
584                         {
585                                 char* check = matches_qline(u->second->nick);
586                                 if (check)
587                                 {
588                                         snprintf(reason,MAXBUF,"Matched Q-Lined nick: %s",check);
589                                         WriteOpers("*** Q-Lined nickname %s from %s: %s",u->second->nick,u->second->host,check);
590                                         WriteServ(u->second->fd,"432 %s %s :Invalid nickname: %s",u->second->nick,u->second->nick,check);
591                                         kill_link(u->second,reason);
592                                         go_again = true;
593                                         break;
594                                 }
595                         }
596                 }
597
598                 for (user_hash::const_iterator u = clientlist.begin(); u != clientlist.end(); u++)
599                 {
600                         if (!strcasecmp(u->second->server,ServerName))
601                         {
602                                 char* check = matches_zline(u->second->ip);
603                                 if (check)
604                                 {
605                                         WriteOpers("*** User %s matches Z-Line: %s",u->second->nick,u->second->host,check);
606                                         WriteServ(u->second->fd,"432 %s %s :Invalid nickname: %s",u->second->nick,u->second->nick,check);
607                                         go_again = true;
608                                         break;
609                                 }
610                         }
611                 }
612
613         }
614 }
615
616 void stats_k(userrec* user)
617 {
618         for (std::vector<KLine>::iterator i = klines.begin(); i != klines.end(); i++)
619         {
620                 WriteServ(user->fd,"216 %s :%s %d %d %s %s",user->nick,i->hostmask,i->set_time,i->duration,i->source,i->reason);
621         }
622 }
623
624 void stats_g(userrec* user)
625 {
626         for (std::vector<GLine>::iterator i = glines.begin(); i != glines.end(); i++)
627         {
628                 WriteServ(user->fd,"223 %s :%s %d %d %s %s",user->nick,i->hostmask,i->set_time,i->duration,i->source,i->reason);
629         }
630 }
631
632 void stats_q(userrec* user)
633 {
634         for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
635         {
636                 WriteServ(user->fd,"217 %s :%s %d %d %s %s",user->nick,i->nick,i->set_time,i->duration,i->source,i->reason);
637         }
638 }
639
640 void stats_z(userrec* user)
641 {
642         for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
643         {
644                 WriteServ(user->fd,"223 %s :%s %d %d %s %s",user->nick,i->ipaddr,i->set_time,i->duration,i->source,i->reason);
645         }
646 }
647
648
649