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