00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "inspircd.h"
00015
00016
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
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 ¶meter)
00043 {
00044
00045 ConfigReader* Conf = new ConfigReader(ServerInstance);
00046
00047
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> ¶meters, 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
00094 override_t::iterator j = overrides.find(source->oper);
00095
00096 if (j != overrides.end())
00097 {
00098
00099 return ((j->second.find(token, 0) != std::string::npos) || (j->second.find("*", 0) != std::string::npos));
00100 }
00101
00102
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
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
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
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
00145
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
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
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
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
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)