]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_override.cpp
Add extra parameter to OnUserPreNotice and OnUserPrePrivmsg, CUList &exempt_list...
[user/henk/code/inspircd.git] / src / modules / m_override.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  InspIRCd is copyright (C) 2002-2006 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 "users.h"
18 #include "channels.h"
19 #include "modules.h"
20 #include "configreader.h"
21 #include "inspircd.h"
22 #include "wildcard.h"
23
24 /* $ModDesc: Provides support for unreal-style oper-override */
25
26 typedef std::map<std::string,std::string> override_t;
27
28 class ModuleOverride : public Module
29 {
30         
31         override_t overrides;
32         bool NoisyOverride;
33         bool OverriddenMode;
34         int OverOps, OverDeops, OverVoices, OverDevoices, OverHalfops, OverDehalfops;
35
36  public:
37  
38         ModuleOverride(InspIRCd* Me)
39                 : Module::Module(Me)
40         {               
41                 // read our config options (main config file)
42                 OnRehash("");
43                 ServerInstance->SNO->EnableSnomask('O',"OVERRIDE");
44                 OverriddenMode = false;
45                 OverOps = OverDeops = OverVoices = OverDevoices = OverHalfops = OverDehalfops = 0;
46         }
47         
48         virtual void OnRehash(const std::string &parameter)
49         {
50                 // on a rehash we delete our classes for good measure and create them again.
51                 ConfigReader* Conf = new ConfigReader(ServerInstance);
52                 
53                 // re-read our config options on a rehash
54                 NoisyOverride = Conf->ReadFlag("override","noisy",0);
55                 overrides.clear();
56                 for (int j =0; j < Conf->Enumerate("type"); j++)
57                 {
58                         std::string typen = Conf->ReadValue("type","name",j);
59                         std::string tokenlist = Conf->ReadValue("type","override",j);
60                         overrides[typen] = tokenlist;
61                 }
62                 
63                 DELETE(Conf);
64         }
65
66         void Implements(char* List)
67         {
68                 List[I_OnRehash] = List[I_OnAccessCheck] = List[I_On005Numeric] = List[I_OnUserPreJoin] = List[I_OnUserPreKick] = List[I_OnPostCommand] = 1;
69         }
70
71         virtual void OnPostCommand(const std::string &command, const char** parameters, int pcnt, userrec *user, CmdResult result, const std::string &original_line)
72         {
73                 if ((NoisyOverride) && (OverriddenMode) && (irc::string(command.c_str()) == "MODE") && (result == CMD_SUCCESS))
74                 {
75                         int Total = OverOps + OverDeops + OverVoices + OverDevoices + OverHalfops + OverDehalfops;
76
77                         ServerInstance->SNO->WriteToSnoMask('O',std::string(user->nick)+" Overriding modes: "+ServerInstance->Modes->GetLastParse()+" "+(Total ? "[Detail: " : "")+
78                                         (OverOps ? ConvToStr(OverOps)+" op"+(OverOps != 1 ? "s" : "")+" " : "")+
79                                         (OverDeops ? ConvToStr(OverDeops)+" deop"+(OverDeops != 1 ? "s" : "")+" " : "")+
80                                         (OverVoices ? ConvToStr(OverVoices)+" voice"+(OverVoices != 1 ? "s" : "")+" " : "")+
81                                         (OverDevoices ? ConvToStr(OverDevoices)+" devoice"+(OverDevoices != 1 ? "s" : "")+" " : "")+
82                                         (OverHalfops ? ConvToStr(OverHalfops)+" halfop"+(OverHalfops != 1 ? "s" : "")+" " : "")+
83                                         (OverDehalfops ? ConvToStr(OverDehalfops)+" dehalfop"+(OverDehalfops != 1 ? "s" : "") : "")
84                                         +(Total ? "]" : ""));
85
86                         OverriddenMode = false;
87                         OverOps = OverDeops = OverVoices = OverDevoices = OverHalfops = OverDehalfops = 0;
88                 }
89         }
90
91         virtual void On005Numeric(std::string &output)
92         {
93                 output.append(" OVERRIDE");
94         }
95
96         virtual bool CanOverride(userrec* source, char* token)
97         {
98                 // checks to see if the oper's type has <type:override>
99                 override_t::iterator j = overrides.find(source->oper);
100
101                 if (j != overrides.end())
102                 {
103                         // its defined or * is set, return its value as a boolean for if the token is set
104                         return ((j->second.find(token, 0) != std::string::npos) || (j->second.find("*", 0) != std::string::npos));
105                 }
106
107                 // its not defined at all, count as false
108                 return false;
109         }
110
111         virtual int OnUserPreKick(userrec* source, userrec* user, chanrec* chan, const std::string &reason)
112         {
113                 if ((*source->oper) && (CanOverride(source,"KICK")))
114                 {
115                         if (((chan->GetStatus(source) == STATUS_HOP) && (chan->GetStatus(user) == STATUS_OP)) || (chan->GetStatus(source) < STATUS_VOICE))
116                         {
117                                 ServerInstance->SNO->WriteToSnoMask('O',std::string(source->nick)+" Override-Kicked "+std::string(user->nick)+" on "+std::string(chan->name)+" ("+reason+")");
118                         }
119                         /* Returning -1 explicitly allows the kick */
120                         return -1;
121                 }
122                 return 0;
123         }
124         
125         virtual int OnAccessCheck(userrec* source,userrec* dest,chanrec* channel,int access_type)
126         {
127                 if (*source->oper)
128                 {
129                         if (source && channel)
130                         {
131                                 // Fix by brain - allow the change if they arent on channel - rely on boolean short-circuit
132                                 // to not check the other items in the statement if they arent on the channel
133                                 int mode = channel->GetStatus(source);
134                                 switch (access_type)
135                                 {
136                                         case AC_DEOP:
137                                                 ServerInstance->Log(DEBUG,"Override access check AC_DEOP");
138                                                 if (CanOverride(source,"MODEDEOP"))
139                                                 {
140                                                         if (NoisyOverride)
141                                                         if ((!channel->HasUser(source)) || (mode < STATUS_OP))
142                                                                 OverDeops++;
143                                                         return ACR_ALLOW;
144                                                 }
145                                                 else
146                                                 {
147                                                         return ACR_DEFAULT;
148                                                 }
149                                         break;
150                                         case AC_OP:
151                                                 ServerInstance->Log(DEBUG,"Override access check AC_OP");
152                                                 if (CanOverride(source,"MODEOP"))
153                                                 {
154                                                         if (NoisyOverride)
155                                                         if ((!channel->HasUser(source)) || (mode < STATUS_OP))
156                                                                 OverOps++;
157                                                         return ACR_ALLOW;
158                                                 }
159                                                 else
160                                                 {
161                                                         return ACR_DEFAULT;
162                                                 }
163                                         break;
164                                         case AC_VOICE:
165                                                 ServerInstance->Log(DEBUG,"Override access check AC_VOICE");
166                                                 if (CanOverride(source,"MODEVOICE"))
167                                                 {
168                                                         if (NoisyOverride)
169                                                         if ((!channel->HasUser(source)) || (mode < STATUS_HOP))
170                                                                 OverVoices++;
171                                                         return ACR_ALLOW;
172                                                 }
173                                                 else
174                                                 {
175                                                         return ACR_DEFAULT;
176                                                 }
177                                         break;
178                                         case AC_DEVOICE:
179                                                 ServerInstance->Log(DEBUG,"Override access check AC_DEVOICE");
180                                                 if (CanOverride(source,"MODEDEVOICE"))
181                                                 {
182                                                         if (NoisyOverride)
183                                                         if ((!channel->HasUser(source)) || (mode < STATUS_HOP))
184                                                                 OverDevoices++;
185                                                         return ACR_ALLOW;
186                                                 }
187                                                 else
188                                                 {
189                                                         return ACR_DEFAULT;
190                                                 }
191                                         break;
192                                         case AC_HALFOP:
193                                                 ServerInstance->Log(DEBUG,"Override access check AC_HALFOP");
194                                                 if (CanOverride(source,"MODEHALFOP"))
195                                                 {
196                                                         if (NoisyOverride)
197                                                         if ((!channel->HasUser(source)) || (mode < STATUS_OP))
198                                                                 OverHalfops++;
199                                                         return ACR_ALLOW;
200                                                 }
201                                                 else
202                                                 {
203                                                         return ACR_DEFAULT;
204                                                 }
205                                         break;
206                                         case AC_DEHALFOP:
207                                                 ServerInstance->Log(DEBUG,"Override access check AC_DEHALFOP");
208                                                 if (CanOverride(source,"MODEDEHALFOP"))
209                                                 {
210                                                         if (NoisyOverride)
211                                                         if ((!channel->HasUser(source)) || (mode < STATUS_OP))
212                                                                 OverDehalfops++;
213                                                         return ACR_ALLOW;
214                                                 }
215                                                 else
216                                                 {
217                                                         return ACR_DEFAULT;
218                                                 }
219                                         break;
220                                 }
221                         
222                                 if (CanOverride(source,"OTHERMODE"))
223                                 {
224                                         if (NoisyOverride)
225                                         if ((!channel->HasUser(source)) || (mode < STATUS_OP))
226                                         {
227                                                 ServerInstance->Log(DEBUG,"Overridden mode");
228                                                 OverriddenMode = true;
229                                                 OverOps = OverDeops = OverVoices = OverDevoices = OverHalfops = OverDehalfops = 0;
230                                         }
231                                         return ACR_ALLOW;
232                                 }
233                                 else
234                                 {
235                                         return ACR_DEFAULT;
236                                 }
237                         }
238                 }
239
240                 return ACR_DEFAULT;
241         }
242         
243         virtual int OnUserPreJoin(userrec* user, chanrec* chan, const char* cname, std::string &privs)
244         {
245                 if (*user->oper)
246                 {
247                         if (chan)
248                         {
249                                 if ((chan->modes[CM_INVITEONLY]) && (CanOverride(user,"INVITE")))
250                                 {
251                                         irc::string x = chan->name;
252                                         if (!user->IsInvited(x))
253                                         {
254                                                 /* XXX - Ugly cast for a parameter that isn't used? :< - Om */
255                                                 if (NoisyOverride)
256                                                         chan->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :%s used oper-override to bypass invite-only", cname, user->nick);
257                                                 ServerInstance->SNO->WriteToSnoMask('O',std::string(user->nick)+" used operoverride to bypass +i on "+std::string(cname));
258                                         }
259                                         return -1;
260                                 }
261                                 
262                                 if ((*chan->key) && (CanOverride(user,"KEY")))
263                                 {
264                                         if (NoisyOverride)
265                                                 chan->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :%s used oper-override to bypass the channel key", cname, user->nick);
266                                         ServerInstance->SNO->WriteToSnoMask('O',std::string(user->nick)+" used operoverride to bypass +k on "+std::string(cname));
267                                         return -1;
268                                 }
269                                         
270                                 if ((chan->limit > 0) && (chan->GetUserCounter() >=  chan->limit) && (CanOverride(user,"LIMIT")))
271                                 {
272                                         if (NoisyOverride)
273                                                 chan->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :%s used oper-override to bypass the channel limit", cname, user->nick);
274                                         ServerInstance->SNO->WriteToSnoMask('O',std::string(user->nick)+" used operoverride to bypass +l on "+std::string(cname));
275                                         return -1;
276                                 }
277
278                                 if (CanOverride(user,"BANWALK"))
279                                 {
280                                         if (chan->IsBanned(user))
281                                         {
282                                                 if (NoisyOverride)
283                                                         chan->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :%s used oper-override to bypass channel ban", cname, user->nick);
284                                                 ServerInstance->SNO->WriteToSnoMask('O',"%s used oper-override to bypass channel ban on %s", user->nick, cname);
285                                         }
286                                         return -1;
287                                 }
288                         }
289                 }
290                 return 0;
291         }
292         
293         virtual ~ModuleOverride()
294         {
295                 ServerInstance->SNO->DisableSnomask('O');
296         }
297         
298         virtual Version GetVersion()
299         {
300                 return Version(1,1,0,1,VF_VENDOR,API_VERSION);
301         }
302 };
303
304
305 class ModuleOverrideFactory : public ModuleFactory
306 {
307  public:
308         ModuleOverrideFactory()
309         {
310         }
311         
312         ~ModuleOverrideFactory()
313         {
314         }
315         
316         virtual Module * CreateModule(InspIRCd* Me)
317         {
318                 return new ModuleOverride(Me);
319         }
320         
321 };
322
323
324 extern "C" void * init_module( void )
325 {
326         return new ModuleOverrideFactory;
327 }