The InspIRCd Project
Home | Developers | Wiki | Forums | Bug Tracker | SVN | Download
Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

m_override.cpp

Go to the documentation of this file.
00001 /*       +------------------------------------+
00002  *       | Inspire Internet Relay Chat Daemon |
00003  *       +------------------------------------+
00004  *
00005  *  InspIRCd: (C) 2002-2008 InspIRCd Development Team
00006  * See: http://www.inspircd.org/wiki/index.php/Credits
00007  *
00008  * This program is free but copyrighted software; see
00009  *            the file COPYING for details.
00010  *
00011  * ---------------------------------------------------
00012  */
00013 
00014 #include "inspircd.h"
00015 
00016 /* $ModDesc: Provides support for unreal-style oper-override */
00017 
00018 typedef std::map<std::string,std::string> override_t;
00019 
00020 class ModuleOverride : public Module
00021 {
00022         override_t overrides;
00023         bool RequireKey;
00024         bool NoisyOverride;
00025         bool OverriddenMode;
00026         int OverOps, OverDeops, OverVoices, OverDevoices, OverHalfops, OverDehalfops;
00027 
00028  public:
00029 
00030         ModuleOverride(InspIRCd* Me)
00031                 : Module(Me)
00032         {
00033                 // read our config options (main config file)
00034                 OnRehash(NULL,"");
00035                 ServerInstance->SNO->EnableSnomask('G', "GODMODE");
00036                 OverriddenMode = false;
00037                 OverOps = OverDeops = OverVoices = OverDevoices = OverHalfops = OverDehalfops = 0;
00038                 Implementation eventlist[] = { I_OnRehash, I_OnAccessCheck, I_On005Numeric, I_OnUserPreJoin, I_OnUserPreKick, I_OnPostCommand, I_OnLocalTopicChange };
00039                 ServerInstance->Modules->Attach(eventlist, this, 7);
00040         }
00041 
00042         virtual void OnRehash(User* user, const std::string &parameter)
00043         {
00044                 // on a rehash we delete our classes for good measure and create them again.
00045                 ConfigReader* Conf = new ConfigReader(ServerInstance);
00046 
00047                 // re-read our config options on a rehash
00048                 NoisyOverride = Conf->ReadFlag("override", "noisy", 0);
00049                 RequireKey = Conf->ReadFlag("override", "requirekey", 0);
00050 
00051                 overrides.clear();
00052 
00053                 for (int j =0; j < Conf->Enumerate("type"); j++)
00054                 {
00055                         std::string typen = Conf->ReadValue("type","name",j);
00056                         std::string tokenlist = Conf->ReadValue("type","override",j);
00057                         overrides[typen] = tokenlist;
00058                 }
00059 
00060                 delete Conf;
00061         }
00062 
00063 
00064         virtual void OnPostCommand(const std::string &command, const std::vector<std::string> &parameters, User *user, CmdResult result, const std::string &original_line)
00065         {
00066                 if ((OverriddenMode) && (irc::string(command.c_str()) == "MODE") && (result == CMD_SUCCESS))
00067                 {
00068                         int Total = OverOps + OverDeops + OverVoices + OverDevoices + OverHalfops + OverDehalfops;
00069                         if (Total == 0)
00070                                 return;
00071 
00072                         ServerInstance->SNO->WriteToSnoMask('G',std::string(user->nick)+" Overriding modes: "+ServerInstance->Modes->GetLastParse()+" "+(Total ? "[Detail: " : "")+
00073                                         (OverOps ? ConvToStr(OverOps)+" op"+(OverOps != 1 ? "s" : "")+" " : "")+
00074                                         (OverDeops ? ConvToStr(OverDeops)+" deop"+(OverDeops != 1 ? "s" : "")+" " : "")+
00075                                         (OverVoices ? ConvToStr(OverVoices)+" voice"+(OverVoices != 1 ? "s" : "")+" " : "")+
00076                                         (OverDevoices ? ConvToStr(OverDevoices)+" devoice"+(OverDevoices != 1 ? "s" : "")+" " : "")+
00077                                         (OverHalfops ? ConvToStr(OverHalfops)+" halfop"+(OverHalfops != 1 ? "s" : "")+" " : "")+
00078                                         (OverDehalfops ? ConvToStr(OverDehalfops)+" dehalfop"+(OverDehalfops != 1 ? "s" : "") : "")
00079                                         +(Total ? "]" : ""));
00080 
00081                         OverriddenMode = false;
00082                         OverOps = OverDeops = OverVoices = OverDevoices = OverHalfops = OverDehalfops = 0;
00083                 }
00084         }
00085 
00086         virtual void On005Numeric(std::string &output)
00087         {
00088                 output.append(" OVERRIDE");
00089         }
00090 
00091         virtual bool CanOverride(User* source, const char* token)
00092         {
00093                 // checks to see if the oper's type has <type:override>
00094                 override_t::iterator j = overrides.find(source->oper);
00095 
00096                 if (j != overrides.end())
00097                 {
00098                         // its defined or * is set, return its value as a boolean for if the token is set
00099                         return ((j->second.find(token, 0) != std::string::npos) || (j->second.find("*", 0) != std::string::npos));
00100                 }
00101 
00102                 // its not defined at all, count as false
00103                 return false;
00104         }
00105 
00106 
00107         virtual int OnLocalTopicChange(User *source, Channel *channel, const std::string &topic)
00108         {
00109                 if (IS_OPER(source) && CanOverride(source, "TOPIC"))
00110                 {
00111                         if (!channel->HasUser(source) || (channel->IsModeSet('t') && channel->GetStatus(source) < STATUS_HOP))
00112                         {
00113                                 ServerInstance->SNO->WriteToSnoMask('G',std::string(source->nick)+"  used oper override to change a topic on "+std::string(channel->name));
00114                         }
00115 
00116                         // Explicit allow
00117                         return -1;
00118                 }
00119 
00120                 return 0;
00121         }
00122 
00123         virtual int OnUserPreKick(User* source, User* user, Channel* chan, const std::string &reason)
00124         {
00125                 if (IS_OPER(source) && CanOverride(source,"KICK"))
00126                 {
00127                         // If the kicker's status is less than the target's,                    or      the kicker's status is less than or equal to voice
00128                         if ((chan->GetStatus(source) < chan->GetStatus(user))                   || (chan->GetStatus(source) <= STATUS_VOICE))
00129                         {                               
00130                                 ServerInstance->SNO->WriteToSnoMask('G',std::string(source->nick)+" used oper override to kick "+std::string(user->nick)+" on "+std::string(chan->name)+" ("+reason+")");
00131                         }
00132                         /* Returning -1 explicitly allows the kick */
00133                         return -1;
00134                 }
00135                 return 0;
00136         }
00137 
00138         virtual int OnAccessCheck(User* source,User* dest,Channel* channel,int access_type)
00139         {
00140                 if (IS_OPER(source))
00141                 {
00142                         if (source && channel)
00143                         {
00144                                 // Fix by brain - allow the change if they arent on channel - rely on boolean short-circuit
00145                                 // to not check the other items in the statement if they arent on the channel
00146                                 int mode = channel->GetStatus(source);
00147                                 switch (access_type)
00148                                 {
00149                                         case AC_DEOP:
00150                                                 if (CanOverride(source,"MODEDEOP"))
00151                                                 {
00152                                                         if ((!channel->HasUser(source)) || (mode < STATUS_OP))
00153                                                                 OverDeops++;
00154                                                         return ACR_ALLOW;
00155                                                 }
00156                                                 else
00157                                                 {
00158                                                         return ACR_DEFAULT;
00159                                                 }
00160                                         break;
00161                                         case AC_OP:
00162                                                 if (CanOverride(source,"MODEOP"))
00163                                                 {
00164                                                         if ((!channel->HasUser(source)) || (mode < STATUS_OP))
00165                                                                 OverOps++;
00166                                                         return ACR_ALLOW;
00167                                                 }
00168                                                 else
00169                                                 {
00170                                                         return ACR_DEFAULT;
00171                                                 }
00172                                         break;
00173                                         case AC_VOICE:
00174                                                 if (CanOverride(source,"MODEVOICE"))
00175                                                 {
00176                                                         if ((!channel->HasUser(source)) || (mode < STATUS_HOP))
00177                                                                 OverVoices++;
00178                                                         return ACR_ALLOW;
00179                                                 }
00180                                                 else
00181                                                 {
00182                                                         return ACR_DEFAULT;
00183                                                 }
00184                                         break;
00185                                         case AC_DEVOICE:
00186                                                 if (CanOverride(source,"MODEDEVOICE"))
00187                                                 {
00188                                                         if ((!channel->HasUser(source)) || (mode < STATUS_HOP))
00189                                                                 OverDevoices++;
00190                                                         return ACR_ALLOW;
00191                                                 }
00192                                                 else
00193                                                 {
00194                                                         return ACR_DEFAULT;
00195                                                 }
00196                                         break;
00197                                         case AC_HALFOP:
00198                                                 if (CanOverride(source,"MODEHALFOP"))
00199                                                 {
00200                                                         if ((!channel->HasUser(source)) || (mode < STATUS_OP))
00201                                                                 OverHalfops++;
00202                                                         return ACR_ALLOW;
00203                                                 }
00204                                                 else
00205                                                 {
00206                                                         return ACR_DEFAULT;
00207                                                 }
00208                                         break;
00209                                         case AC_DEHALFOP:
00210                                                 if (CanOverride(source,"MODEDEHALFOP"))
00211                                                 {
00212                                                         if ((!channel->HasUser(source)) || (mode < STATUS_OP))
00213                                                                 OverDehalfops++;
00214                                                         return ACR_ALLOW;
00215                                                 }
00216                                                 else
00217                                                 {
00218                                                         return ACR_DEFAULT;
00219                                                 }
00220                                         break;
00221                                 }
00222 
00223                                 if (CanOverride(source,"OTHERMODE"))
00224                                 {
00225                                         if ((!channel->HasUser(source)) || (mode < STATUS_OP))
00226                                         {
00227                                                 OverriddenMode = true;
00228                                                 OverOps = OverDeops = OverVoices = OverDevoices = OverHalfops = OverDehalfops = 0;
00229                                         }
00230                                         return ACR_ALLOW;
00231                                 }
00232                                 else
00233                                 {
00234                                         return ACR_DEFAULT;
00235                                 }
00236                         }
00237                 }
00238 
00239                 return ACR_DEFAULT;
00240         }
00241 
00242         virtual int OnUserPreJoin(User* user, Channel* chan, const char* cname, std::string &privs, const std::string &keygiven)
00243         {
00244                 if (IS_LOCAL(user) && IS_OPER(user))
00245                 {
00246                         if (chan)
00247                         {
00248                                 if ((chan->modes[CM_INVITEONLY]) && (CanOverride(user,"INVITE")))
00249                                 {
00250                                         irc::string x(chan->name.c_str());
00251                                         if (!user->IsInvited(x))
00252                                         {
00253                                                 if (RequireKey && keygiven != "override")
00254                                                 {
00255                                                         // Can't join normally -- must use a special key to bypass restrictions
00256                                                         user->WriteServ("NOTICE %s :*** You may not join normally. You must join with a key of 'override' to oper override.", user->nick.c_str());
00257                                                         return 1;
00258                                                 }
00259 
00260                                                 if (NoisyOverride)
00261                                                         chan->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :%s used oper override to bypass invite-only", cname, user->nick.c_str());
00262                                                 ServerInstance->SNO->WriteToSnoMask('G', user->nick+" used oper override to bypass +i on "+std::string(cname));
00263                                         }
00264                                         return -1;
00265                                 }
00266 
00267                                 if ((chan->modes[CM_KEY]) && (CanOverride(user,"KEY")) && keygiven != chan->GetModeParameter('k'))
00268                                 {
00269                                         if (RequireKey && keygiven != "override")
00270                                         {
00271                                                 // Can't join normally -- must use a special key to bypass restrictions
00272                                                 user->WriteServ("NOTICE %s :*** You may not join normally. You must join with a key of 'override' to oper override.", user->nick.c_str());
00273                                                 return 1;
00274                                         }
00275 
00276                                         if (NoisyOverride)
00277                                                 chan->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :%s used oper override to bypass the channel key", cname, user->nick.c_str());
00278                                         ServerInstance->SNO->WriteToSnoMask('G', user->nick+" used oper override to bypass +k on "+std::string(cname));
00279                                         return -1;
00280                                 }
00281 
00282                                 if ((chan->modes[CM_LIMIT]) && (chan->GetUserCounter() >=  atoi(chan->GetModeParameter('l').c_str())) && (CanOverride(user,"LIMIT")))
00283                                 {
00284                                         if (RequireKey && keygiven != "override")
00285                                         {
00286                                                 // Can't join normally -- must use a special key to bypass restrictions
00287                                                 user->WriteServ("NOTICE %s :*** You may not join normally. You must join with a key of 'override' to oper override.", user->nick.c_str());
00288                                                 return 1;
00289                                         }
00290 
00291                                         if (NoisyOverride)
00292                                                 chan->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :%s used oper override to bypass the channel limit", cname, user->nick.c_str());
00293                                         ServerInstance->SNO->WriteToSnoMask('G', user->nick+" used oper override to bypass +l on "+std::string(cname));
00294                                         return -1;
00295                                 }
00296 
00297                                 if (chan->IsBanned(user) && CanOverride(user,"BANWALK"))
00298                                 {
00299                                         if (RequireKey && keygiven != "override")
00300                                         {
00301                                                 // Can't join normally -- must use a special key to bypass restrictions
00302                                                 user->WriteServ("NOTICE %s :*** You may not join normally. You must join with a key of 'override' to oper override.", user->nick.c_str());
00303                                                 return 1;
00304                                         }
00305 
00306                                         if (NoisyOverride)
00307                                                 chan->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :%s used oper override to bypass channel ban", cname, user->nick.c_str());
00308                                         ServerInstance->SNO->WriteToSnoMask('G',"%s used oper override to bypass channel ban on %s", user->nick.c_str(), cname);
00309                                         return -1;
00310                                 }
00311                         }
00312                 }
00313                 return 0;
00314         }
00315 
00316         virtual ~ModuleOverride()
00317         {
00318                 ServerInstance->SNO->DisableSnomask('G');
00319         }
00320 
00321         virtual Version GetVersion()
00322         {
00323                 return Version("$Id: m_override.cpp 10775 2008-11-01 17:20:47Z w00t $",VF_VENDOR,API_VERSION);
00324         }
00325 };
00326 
00327 MODULE_INIT(ModuleOverride)