From: danieldg Date: Wed, 21 Oct 2009 23:45:44 +0000 (+0000) Subject: Change User::oper to an OperInfo reference X-Git-Tag: v2.0.23~1315 X-Git-Url: https://git.netwichtig.de/gitweb/?a=commitdiff_plain;ds=sidebyside;h=a30abe26fc803900eaf5dc4c08a31aa1d3c9c89f;p=user%2Fhenk%2Fcode%2Finspircd.git Change User::oper to an OperInfo reference git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@11945 e03df62e-2008-0410-955e-edbf42e46eb7 --- diff --git a/include/configreader.h b/include/configreader.h index 3ec4ca826..d4bc4b71b 100644 --- a/include/configreader.h +++ b/include/configreader.h @@ -61,8 +61,6 @@ struct CoreExport ConfigTag : public refcountbase */ typedef std::multimap > ConfigDataHash; -typedef std::map > TagIndex; - /** Defines the server's length limits on various length-limited * items such as topics, nicknames, channel names etc. */ @@ -112,6 +110,30 @@ class ServerLimits } }; +class CoreExport OperInfo : public refcountbase +{ + public: + /** block used for this oper-up. May be NULL. */ + reference oper_block; + /** block used for this oper-up. Valid for local users, may be NULL on remote */ + reference type_block; + /** blocks referenced from the block. These define individual permissions */ + std::vector > class_blocks; + /** Name of the oper type; i.e. the one shown in WHOIS */ + std::string name; + + /** Get a configuration item, searching in the oper, type, and class blocks (in that order) */ + std::string getConfig(const std::string& key); + + inline const char* NameStr() + { + return irc::Spacify(name.c_str()); + } +}; + +typedef std::map > TagIndex; +typedef std::map > OperIndex; + /** This class holds the bulk of the runtime configuration for the ircd. * It allows for reading new config values, accessing configuration files, * and storage of the configuration data needed to run the ircd, such as @@ -495,13 +517,10 @@ class CoreExport ServerConfig */ bool FullHostInTopic; - /** All oper type definitions from the config file - */ - TagIndex opertypes; - - /** All oper class definitions from the config file + /** Oper block and type index. + * For anonymous oper blocks (type only), prefix with a space. */ - TagIndex operclass; + OperIndex oper_blocks; /** Saved argv from startup */ diff --git a/include/users.h b/include/users.h index 51600e3af..bb8fba007 100644 --- a/include/users.h +++ b/include/users.h @@ -60,6 +60,7 @@ enum RegistrationState { class Channel; class UserResolver; struct ConfigTag; +class OperInfo; /** Holds information relevent to <connect allow> and <connect deny> tags in the config file. */ @@ -348,11 +349,8 @@ class CoreExport User : public StreamSocket time_t awaytime; /** The oper type they logged in as, if they are an oper. - * This is used to check permissions in operclasses, so that - * we can say 'yea' or 'nay' to any commands they issue. - * The value of this was the value of a valid 'type name=' tag */ - std::string oper; + reference oper; /** Used by User to indicate the registration status of the connection * It is a bitfield of the REG_NICK, REG_USER and REG_ALL bits to indicate @@ -530,9 +528,8 @@ class CoreExport User : public StreamSocket /** Oper up the user using the given opertype. * This will also give the +o usermode. - * @param opertype The oper type to oper as */ - void Oper(const std::string &opertype, const std::string &opername); + void Oper(OperInfo* info); /** Change this users hash key to a new string. * You should not call this function directly. It is used by the core @@ -949,7 +946,7 @@ inline FakeUser* IS_SERVER(User* u) return u->GetFd() == FD_FAKEUSER_NUMBER ? static_cast(u) : NULL; } /** Is an oper */ -#define IS_OPER(x) (!x->oper.empty()) +#define IS_OPER(x) (x->oper) /** Is away */ #define IS_AWAY(x) (!x->awaymsg.empty()) diff --git a/src/command_parse.cpp b/src/command_parse.cpp index 9fc8f85bb..883507058 100644 --- a/src/command_parse.cpp +++ b/src/command_parse.cpp @@ -340,7 +340,8 @@ bool CommandParser::ProcessCommand(User *user, std::string &cmd) } if (!user->HasPermission(command)) { - user->WriteNumeric(ERR_NOPRIVILEGES, "%s :Permission Denied - Oper type %s does not have access to command %s",user->nick.c_str(),irc::Spacify(user->oper.c_str()),command.c_str()); + user->WriteNumeric(ERR_NOPRIVILEGES, "%s :Permission Denied - Oper type %s does not have access to command %s", + user->nick.c_str(), user->oper->NameStr(), command.c_str()); return do_more; } } diff --git a/src/commands/cmd_oper.cpp b/src/commands/cmd_oper.cpp index 428e7b109..b2db8c95c 100644 --- a/src/commands/cmd_oper.cpp +++ b/src/commands/cmd_oper.cpp @@ -54,8 +54,6 @@ CmdResult CommandOper::HandleLocal(const std::vector& parameters, L { char TheHost[MAXBUF]; char TheIP[MAXBUF]; - std::string type; - bool found = false; bool match_login = false; bool match_pass = false; bool match_hosts = false; @@ -63,89 +61,51 @@ CmdResult CommandOper::HandleLocal(const std::vector& parameters, L snprintf(TheHost,MAXBUF,"%s@%s",user->ident.c_str(),user->host.c_str()); snprintf(TheIP, MAXBUF,"%s@%s",user->ident.c_str(),user->GetIPString()); - for (int i = 0;; i++) + OperIndex::iterator i = ServerInstance->Config->oper_blocks.find(parameters[0]); + if (i != ServerInstance->Config->oper_blocks.end()) { - ConfigTag* tag = ServerInstance->Config->ConfValue("oper", i); - if (!tag) - break; - if (tag->getString("name") != parameters[0]) - continue; + OperInfo* ifo = i->second; + ConfigTag* tag = ifo->oper_block; match_login = true; match_pass = !ServerInstance->PassCompare(user, tag->getString("password"), parameters[1], tag->getString("hash")); match_hosts = OneOfMatches(TheHost,TheIP,tag->getString("host")); if (match_pass && match_hosts) { - type = tag->getString("type"); - ConfigTag* typeTag = ServerInstance->Config->opertypes[type]; - - if (typeTag) + /* found this oper's opertype */ + std::string host = ifo->getConfig("host"); + if (!host.empty()) + user->ChangeDisplayedHost(host.c_str()); + std::string opClass = ifo->getConfig("class"); + if (!opClass.empty()) { - /* found this oper's opertype */ - if (!ServerInstance->IsNick(type.c_str(), ServerInstance->Config->Limits.NickMax)) - { - user->WriteNumeric(491, "%s :Invalid oper type (oper types must follow the same syntax as nicknames)",user->nick.c_str()); - ServerInstance->SNO->WriteToSnoMask('o',"CONFIGURATION ERROR! Oper type '%s' contains invalid characters",type.c_str()); - ServerInstance->Logs->Log("OPER",DEFAULT,"OPER: Failed oper attempt by %s!%s@%s: credentials valid, but oper type erroneous.", user->nick.c_str(), user->ident.c_str(), user->host.c_str()); - return CMD_FAILURE; - } - std::string host = typeTag->getString("host"); - if (!host.empty()) - user->ChangeDisplayedHost(host.c_str()); - std::string opClass = typeTag->getString("class"); - if (!opClass.empty()) - { - user->SetClass(opClass); - user->CheckClass(); - } - found = true; + user->SetClass(opClass); + user->CheckClass(); } - } - break; - } - if (found) - { - /* correct oper credentials */ - user->Oper(type, parameters[0]); - } - else - { - char broadcast[MAXBUF]; - - if (type.empty()) - { - std::string fields; - if (!match_login) - fields.append("login "); - if (!match_pass) - fields.append("password "); - if (!match_hosts) - fields.append("hosts"); - - // tell them they suck, and lag them up to help prevent brute-force attacks - user->WriteNumeric(491, "%s :Invalid oper credentials",user->nick.c_str()); - user->Penalty += 10; - - snprintf(broadcast, MAXBUF, "WARNING! Failed oper attempt by %s!%s@%s using login '%s': The following fields do not match: %s", user->nick.c_str(), user->ident.c_str(), user->host.c_str(), parameters[0].c_str(), fields.c_str()); - ServerInstance->SNO->WriteToSnoMask('o',std::string(broadcast)); - ServerInstance->PI->SendSNONotice("o", std::string("OPER: ") + broadcast); - - ServerInstance->Logs->Log("OPER",DEFAULT,"OPER: Failed oper attempt by %s!%s@%s using login '%s': The following fields did not match: %s", user->nick.c_str(), user->ident.c_str(), user->host.c_str(), parameters[0].c_str(), fields.c_str()); - return CMD_FAILURE; - } - else - { - user->WriteNumeric(491, "%s :Your oper block does not have a valid opertype associated with it",user->nick.c_str()); - - snprintf(broadcast, MAXBUF, "CONFIGURATION ERROR! Oper block '%s': missing OperType %s",parameters[0].c_str(),type.c_str()); - - ServerInstance->SNO->WriteToSnoMask('o', std::string(broadcast)); - - ServerInstance->Logs->Log("OPER",DEFAULT,"OPER: Failed oper attempt by %s!%s@%s using login '%s': credentials valid, but oper type nonexistent.", user->nick.c_str(), user->ident.c_str(), user->host.c_str(), parameters[0].c_str()); - return CMD_FAILURE; + user->Oper(ifo); + return CMD_SUCCESS; } } - return CMD_SUCCESS; + char broadcast[MAXBUF]; + + std::string fields; + if (!match_login) + fields.append("login "); + if (!match_pass) + fields.append("password "); + if (!match_hosts) + fields.append("hosts"); + + // tell them they suck, and lag them up to help prevent brute-force attacks + user->WriteNumeric(491, "%s :Invalid oper credentials",user->nick.c_str()); + user->Penalty += 10; + + snprintf(broadcast, MAXBUF, "WARNING! Failed oper attempt by %s!%s@%s using login '%s': The following fields do not match: %s", user->nick.c_str(), user->ident.c_str(), user->host.c_str(), parameters[0].c_str(), fields.c_str()); + ServerInstance->SNO->WriteToSnoMask('o',std::string(broadcast)); + ServerInstance->PI->SendSNONotice("o", std::string("OPER: ") + broadcast); + + ServerInstance->Logs->Log("OPER",DEFAULT,"OPER: Failed oper attempt by %s!%s@%s using login '%s': The following fields did not match: %s", user->nick.c_str(), user->ident.c_str(), user->host.c_str(), parameters[0].c_str(), fields.c_str()); + return CMD_FAILURE; } COMMAND_INIT(CommandOper) diff --git a/src/configreader.cpp b/src/configreader.cpp index 6932e960e..5d47e1931 100644 --- a/src/configreader.cpp +++ b/src/configreader.cpp @@ -589,8 +589,10 @@ static void ReadXLine(ServerConfig* conf, const std::string& tag, const std::str } } +typedef std::map LocalIndex; void ServerConfig::CrossCheckOperClassType() { + LocalIndex operclass; for (int i = 0;; ++i) { ConfigTag* tag = ConfValue("class", i); @@ -610,16 +612,49 @@ void ServerConfig::CrossCheckOperClassType() std::string name = tag->getString("name"); if (name.empty()) throw CoreException(" is missing from tag at " + tag->getTagLocation()); - opertypes[name] = tag; + + if (!ServerInstance->IsNick(name.c_str(), Limits.NickMax)) + throw CoreException(" is invalid (value '" + name + "')"); + + OperInfo* ifo = new OperInfo; + oper_blocks[" " + name] = ifo; + ifo->type_block = tag; std::string classname; irc::spacesepstream str(tag->getString("classes")); while (str.GetToken(classname)) { - if (operclass.find(classname) == operclass.end()) + LocalIndex::iterator cls = operclass.find(classname); + if (cls == operclass.end()) throw CoreException("Oper type " + name + " has missing class " + classname); + ifo->class_blocks.push_back(cls->second); } } + + for (int i = 0;; ++i) + { + ConfigTag* tag = ConfValue("oper", i); + if (!tag) + break; + + std::string name = tag->getString("name"); + if (name.empty()) + throw CoreException(" missing from tag at " + tag->getTagLocation()); + + std::string type = tag->getString("type"); + OperIndex::iterator tblk = oper_blocks.find(" " + type); + if (tblk == oper_blocks.end()) + throw CoreException("Oper block " + name + " has missing type " + type); + if (oper_blocks.find(name) != oper_blocks.end()) + throw CoreException("Duplicate oper block with name " + name); + + OperInfo* ifo = new OperInfo; + ifo->name = type; + ifo->oper_block = tag; + ifo->type_block = tblk->second->type_block; + ifo->class_blocks.assign(tblk->second->class_blocks.begin(), tblk->second->class_blocks.end()); + oper_blocks[name] = ifo; + } } void ServerConfig::CrossCheckConnectBlocks(ServerConfig* current) @@ -1255,6 +1290,16 @@ std::string ConfigTag::getTagLocation() return src_name + ":" + ConvToStr(src_line); } +std::string OperInfo::getConfig(const std::string& key) +{ + std::string rv; + if (type_block) + type_block->readString(key, rv); + if (oper_block) + oper_block->readString(key, rv); + return rv; +} + /** Read the contents of a file located by `fname' into a file_cache pointed at by `F'. */ bool ServerConfig::ReadFile(file_cache &F, const std::string& fname) diff --git a/src/mode.cpp b/src/mode.cpp index c8ab6cc62..d19647cae 100644 --- a/src/mode.cpp +++ b/src/mode.cpp @@ -336,7 +336,7 @@ ModeAction ModeParser::TryMode(User* user, User* targetuser, Channel* chan, bool if (IS_OPER(user)) { user->WriteNumeric(ERR_NOPRIVILEGES, "%s :Permission Denied - Oper type %s does not have access to set %s mode %c", - user->nick.c_str(), irc::Spacify(user->oper.c_str()), type == MODETYPE_CHANNEL ? "channel" : "user", modechar); + user->nick.c_str(), user->oper->NameStr(), type == MODETYPE_CHANNEL ? "channel" : "user", modechar); } else { diff --git a/src/modes/umode_o.cpp b/src/modes/umode_o.cpp index d5014fc68..1f8d77950 100644 --- a/src/modes/umode_o.cpp +++ b/src/modes/umode_o.cpp @@ -25,7 +25,7 @@ ModeUserOperator::ModeUserOperator() : ModeHandler(NULL, "oper", 'o', PARAM_NONE ModeAction ModeUserOperator::OnModeChange(User* source, User* dest, Channel*, std::string&, bool adding) { /* Only opers can execute this class at all */ - if (!ServerInstance->ULine(source->nick.c_str()) && !ServerInstance->ULine(source->server) && source->oper.empty()) + if (!ServerInstance->ULine(source->nick.c_str()) && !ServerInstance->ULine(source->server) && !IS_OPER(source)) return MODEACTION_DENY; /* Not even opers can GIVE the +o mode, only take it away */ diff --git a/src/modules/m_check.cpp b/src/modules/m_check.cpp index 51fee9fe5..158b0c533 100644 --- a/src/modules/m_check.cpp +++ b/src/modules/m_check.cpp @@ -98,7 +98,7 @@ class CommandCheck : public Command if (IS_OPER(targuser)) { /* user is an oper of type ____ */ - user->SendText(checkstr + " opertype " + irc::Spacify(targuser->oper.c_str())); + user->SendText(checkstr + " opertype " + targuser->oper->NameStr()); } LocalUser* loctarg = IS_LOCAL(targuser); diff --git a/src/modules/m_httpd_stats.cpp b/src/modules/m_httpd_stats.cpp index 3339a9ca8..8899a363e 100644 --- a/src/modules/m_httpd_stats.cpp +++ b/src/modules/m_httpd_stats.cpp @@ -167,7 +167,7 @@ class ModuleHttpStats : public Module if (IS_AWAY(u)) data << "" << Sanitize(u->awaymsg) << "" << u->awaytime << ""; if (IS_OPER(u)) - data << "" << Sanitize(u->oper) << ""; + data << "" << Sanitize(u->oper->NameStr()) << ""; data << "" << u->FormatModes() << "" << Sanitize(u->ident) << ""; LocalUser* lu = IS_LOCAL(u); if (lu) diff --git a/src/modules/m_operchans.cpp b/src/modules/m_operchans.cpp index 4f73e0969..205d9a412 100644 --- a/src/modules/m_operchans.cpp +++ b/src/modules/m_operchans.cpp @@ -71,7 +71,7 @@ class ModuleOperChans : public Module { if (mask[0] == 'O' && mask[1] == ':') { - if (IS_OPER(user) && InspIRCd::Match(user->oper, mask.substr(2))) + if (IS_OPER(user) && InspIRCd::Match(user->oper->name, mask.substr(2))) return MOD_RES_DENY; } return MOD_RES_PASSTHRU; diff --git a/src/modules/m_operjoin.cpp b/src/modules/m_operjoin.cpp index 42b30f6fb..469bb6a2c 100644 --- a/src/modules/m_operjoin.cpp +++ b/src/modules/m_operjoin.cpp @@ -92,7 +92,7 @@ class ModuleOperjoin : public Module if (ServerInstance->IsChannel(it->c_str(), ServerInstance->Config->Limits.ChanMax)) Channel::JoinUser(user, it->c_str(), override, "", false, ServerInstance->Time()); - std::map >::iterator i = operTypeChans.find(user->oper); + std::map >::iterator i = operTypeChans.find(user->oper->name); if (i != operTypeChans.end()) { diff --git a/src/modules/m_operlevels.cpp b/src/modules/m_operlevels.cpp index 7a18991c1..6aaa2f48e 100644 --- a/src/modules/m_operlevels.cpp +++ b/src/modules/m_operlevels.cpp @@ -42,16 +42,8 @@ class ModuleOperLevels : public Module // oper killing an oper? if (IS_OPER(dest) && IS_OPER(source)) { - TagIndex::iterator dest_type = ServerInstance->Config->opertypes.find(dest->oper); - TagIndex::iterator src_type = ServerInstance->Config->opertypes.find(source->oper); - - if (dest_type == ServerInstance->Config->opertypes.end()) - return MOD_RES_PASSTHRU; - if (src_type == ServerInstance->Config->opertypes.end()) - return MOD_RES_PASSTHRU; - - long dest_level = dest_type->second->getInt("level"); - long source_level = src_type->second->getInt("level"); + long dest_level = atol(dest->oper->getConfig("level").c_str()); + long source_level = atol(source->oper->getConfig("level").c_str()); if (dest_level > source_level) { if (IS_LOCAL(source)) ServerInstance->SNO->WriteGlobalSno('a', "Oper %s (level %ld) attempted to /kill a higher oper: %s (level %ld): Reason: %s",source->nick.c_str(),source_level,dest->nick.c_str(),dest_level,reason.c_str()); diff --git a/src/modules/m_opermodes.cpp b/src/modules/m_opermodes.cpp index 9db0b5b4a..6b5ca10f9 100644 --- a/src/modules/m_opermodes.cpp +++ b/src/modules/m_opermodes.cpp @@ -40,13 +40,10 @@ class ModuleModesOnOper : public Module virtual void OnPostOper(User* user, const std::string &opertype, const std::string &opername) { - TagIndex::iterator typetag = ServerInstance->Config->opertypes.find(opertype); - if (typetag == ServerInstance->Config->opertypes.end()) - return; // whenever a user opers, go through the oper types, find their , // and if they have one apply their modes. The mode string can contain +modes // to add modes to the user or -modes to take modes from the user. - std::string ThisOpersModes = typetag->second->getString("modes"); + std::string ThisOpersModes = user->oper->getConfig("modes"); if (!ThisOpersModes.empty()) { ApplyModes(user, ThisOpersModes); diff --git a/src/modules/m_override.cpp b/src/modules/m_override.cpp index 8a3fcdd62..cf18495b5 100644 --- a/src/modules/m_override.cpp +++ b/src/modules/m_override.cpp @@ -61,7 +61,7 @@ class ModuleOverride : public Module bool CanOverride(User* source, const char* token) { // checks to see if the oper's type has - override_t::iterator j = overrides.find(source->oper); + override_t::iterator j = overrides.find(source->oper->name); if (j != overrides.end()) { diff --git a/src/modules/m_spanningtree/netburst.cpp b/src/modules/m_spanningtree/netburst.cpp index 5f47c690b..82b6c2b68 100644 --- a/src/modules/m_spanningtree/netburst.cpp +++ b/src/modules/m_spanningtree/netburst.cpp @@ -259,7 +259,7 @@ void TreeSocket::SendUsers(TreeServer* Current) this->WriteLine(data); if (IS_OPER(u->second)) { - snprintf(data,MAXBUF,":%s OPERTYPE %s", u->second->uuid.c_str(), u->second->oper.c_str()); + snprintf(data,MAXBUF,":%s OPERTYPE %s", u->second->uuid.c_str(), u->second->oper->name.c_str()); this->WriteLine(data); } if (IS_AWAY(u->second)) diff --git a/src/modules/m_spanningtree/opertype.cpp b/src/modules/m_spanningtree/opertype.cpp index dc9c0064f..32ffa4fc7 100644 --- a/src/modules/m_spanningtree/opertype.cpp +++ b/src/modules/m_spanningtree/opertype.cpp @@ -35,7 +35,14 @@ bool TreeSocket::OperType(const std::string &prefix, parameterlist ¶ms) if (!IS_OPER(u)) ServerInstance->Users->all_opers.push_back(u); u->modes[UM_OPERATOR] = 1; - u->oper.assign(opertype, 0, 512); + OperIndex::iterator iter = ServerInstance->Config->oper_blocks.find(" " + opertype); + if (iter != ServerInstance->Config->oper_blocks.end()) + u->oper = iter->second; + else + { + u->oper = new OperInfo; + u->oper->name = opertype; + } Utils->DoOneToAllButSender(u->uuid, "OPERTYPE", params, u->server); TreeServer* remoteserver = Utils->FindServer(u->server); diff --git a/src/modules/m_sqloper.cpp b/src/modules/m_sqloper.cpp index c4eaa6911..a6da1ddaa 100644 --- a/src/modules/m_sqloper.cpp +++ b/src/modules/m_sqloper.cpp @@ -275,26 +275,21 @@ public: bool OperUser(User* user, const std::string &pattern, const std::string &type) { - ConfigReader Conf; - - for (int j = 0; j < Conf.Enumerate("type"); j++) - { - std::string tname = Conf.ReadValue("type","name",j); - std::string hostname(user->ident); + OperIndex::iterator iter = ServerInstance->Config->oper_blocks.find(" " + type); + if (iter == ServerInstance->Config->oper_blocks.end()) + return false; + OperInfo* ifo = iter->second; - hostname.append("@").append(user->host); + std::string hostname(user->ident); - if ((tname == type) && OneOfMatches(hostname.c_str(), user->GetIPString(), pattern.c_str())) - { - /* Opertype and host match, looks like this is it. */ - std::string operhost = Conf.ReadValue("type", "host", j); + hostname.append("@").append(user->host); - if (operhost.size()) - user->ChangeDisplayedHost(operhost.c_str()); + if (OneOfMatches(hostname.c_str(), user->GetIPString(), pattern.c_str())) + { + /* Opertype and host match, looks like this is it. */ - user->Oper(type, tname); - return true; - } + user->Oper(ifo); + return true; } return false; diff --git a/src/modules/m_swhois.cpp b/src/modules/m_swhois.cpp index 8949c21ef..4c262c9ca 100644 --- a/src/modules/m_swhois.cpp +++ b/src/modules/m_swhois.cpp @@ -106,32 +106,7 @@ class ModuleSWhois : public Module return; ConfigReader Conf; - std::string swhois; - - for (int i = 0; i < Conf.Enumerate("oper"); i++) - { - std::string name = Conf.ReadValue("oper", "name", i); - - if (name == params[0]) - { - swhois = Conf.ReadValue("oper", "swhois", i); - break; - } - } - - if (!swhois.length()) - { - for (int i = 0; i < Conf.Enumerate("type"); i++) - { - std::string type = Conf.ReadValue("type", "name", i); - - if (type == user->oper) - { - swhois = Conf.ReadValue("type", "swhois", i); - break; - } - } - } + std::string swhois = user->oper->getConfig("swhois"); if (!swhois.length()) return; diff --git a/src/users.cpp b/src/users.cpp index bcf50a1ff..0f760e27c 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -499,7 +499,7 @@ bool LocalUser::HasPrivPermission(const std::string &privstr, bool noisy) } if (noisy) - this->WriteServ("NOTICE %s :Oper type %s does not have access to priv %s", this->nick.c_str(), this->oper.c_str(), privstr.c_str()); + this->WriteServ("NOTICE %s :Oper type %s does not have access to priv %s", this->nick.c_str(), oper->NameStr(), privstr.c_str()); return false; } @@ -637,97 +637,87 @@ CullResult LocalUser::cull() return User::cull(); } -void User::Oper(const std::string &opertype, const std::string &opername) +void User::Oper(OperInfo* info) { if (this->IsModeSet('o')) this->UnOper(); this->modes[UM_OPERATOR] = 1; + this->oper = info; this->WriteServ("MODE %s :+o", this->nick.c_str()); - FOREACH_MOD(I_OnOper, OnOper(this, opertype)); + FOREACH_MOD(I_OnOper, OnOper(this, info->name)); - ServerInstance->SNO->WriteToSnoMask('o',"%s (%s@%s) is now an IRC operator of type %s (using oper '%s')", this->nick.c_str(), this->ident.c_str(), this->host.c_str(), irc::Spacify(opertype.c_str()), opername.c_str()); - this->WriteNumeric(381, "%s :You are now %s %s", this->nick.c_str(), strchr("aeiouAEIOU", *opertype.c_str()) ? "an" : "a", irc::Spacify(opertype.c_str())); + std::string opername; + if (info->oper_block) + opername = info->oper_block->getString("name"); - ServerInstance->Logs->Log("OPER", DEFAULT, "%s!%s@%s opered as type: %s", this->nick.c_str(), this->ident.c_str(), this->host.c_str(), opertype.c_str()); - this->oper.assign(opertype, 0, 512); + ServerInstance->SNO->WriteToSnoMask('o',"%s (%s@%s) is now an IRC operator of type %s (using oper '%s')", + nick.c_str(), ident.c_str(), host.c_str(), info->NameStr(), opername.c_str()); + this->WriteNumeric(381, "%s :You are now %s %s", nick.c_str(), strchr("aeiouAEIOU", info->name[0]) ? "an" : "a", info->NameStr()); + + ServerInstance->Logs->Log("OPER", DEFAULT, "%s!%s@%s opered as type: %s", this->nick.c_str(), this->ident.c_str(), this->host.c_str(), info->NameStr()); ServerInstance->Users->all_opers.push_back(this); if (IS_LOCAL(this)) IS_LOCAL(this)->OperInternal(); - FOREACH_MOD(I_OnPostOper,OnPostOper(this, opertype, opername)); + FOREACH_MOD(I_OnPostOper,OnPostOper(this, info->name, opername)); } void LocalUser::OperInternal() { - /* - * This might look like it's in the wrong place. - * It is *not*! - * - * For multi-network servers, we may not have the opertypes of the remote server, but we still want to mark the user as an oper of that type. - * -- w00t - */ - TagIndex::iterator iter_opertype = ServerInstance->Config->opertypes.find(this->oper.c_str()); - if (iter_opertype != ServerInstance->Config->opertypes.end()) - { - if (AllowedOperCommands) - AllowedOperCommands->clear(); - else - AllowedOperCommands = new std::set; + if (AllowedOperCommands) + AllowedOperCommands->clear(); + else + AllowedOperCommands = new std::set; - if (AllowedPrivs) - AllowedPrivs->clear(); - else - AllowedPrivs = new std::set; + if (AllowedPrivs) + AllowedPrivs->clear(); + else + AllowedPrivs = new std::set; - AllowedUserModes.reset(); - AllowedChanModes.reset(); - this->AllowedUserModes['o' - 'A'] = true; // Call me paranoid if you want. + AllowedUserModes.reset(); + AllowedChanModes.reset(); + this->AllowedUserModes['o' - 'A'] = true; // Call me paranoid if you want. - std::string myclass, mycmd, mypriv; - irc::spacesepstream Classes(iter_opertype->second->getString("classes")); - while (Classes.GetToken(myclass)) + for(std::vector >::iterator iter = oper->class_blocks.begin(); iter != oper->class_blocks.end(); ++iter) + { + ConfigTag* tag = *iter; + std::string mycmd, mypriv; + /* Process commands */ + irc::spacesepstream CommandList(tag->getString("commands")); + while (CommandList.GetToken(mycmd)) { - TagIndex::iterator iter_operclass = ServerInstance->Config->operclass.find(myclass.c_str()); - if (iter_operclass != ServerInstance->Config->operclass.end()) - { - /* Process commands */ - irc::spacesepstream CommandList(iter_operclass->second->getString("commands")); - while (CommandList.GetToken(mycmd)) - { - this->AllowedOperCommands->insert(mycmd); - } + this->AllowedOperCommands->insert(mycmd); + } - irc::spacesepstream PrivList(iter_operclass->second->getString("privs")); - while (PrivList.GetToken(mypriv)) - { - this->AllowedPrivs->insert(mypriv); - } + irc::spacesepstream PrivList(tag->getString("privs")); + while (PrivList.GetToken(mypriv)) + { + this->AllowedPrivs->insert(mypriv); + } - for (unsigned char* c = (unsigned char*)iter_operclass->second->getString("usermodes").c_str(); *c; ++c) - { - if (*c == '*') - { - this->AllowedUserModes.set(); - } - else - { - this->AllowedUserModes[*c - 'A'] = true; - } - } + for (unsigned char* c = (unsigned char*)tag->getString("usermodes").c_str(); *c; ++c) + { + if (*c == '*') + { + this->AllowedUserModes.set(); + } + else + { + this->AllowedUserModes[*c - 'A'] = true; + } + } - for (unsigned char* c = (unsigned char*)iter_operclass->second->getString("chanmodes").c_str(); *c; ++c) - { - if (*c == '*') - { - this->AllowedChanModes.set(); - } - else - { - this->AllowedChanModes[*c - 'A'] = true; - } - } + for (unsigned char* c = (unsigned char*)tag->getString("chanmodes").c_str(); *c; ++c) + { + if (*c == '*') + { + this->AllowedChanModes.set(); + } + else + { + this->AllowedChanModes[*c - 'A'] = true; } } } @@ -743,7 +733,7 @@ void User::UnOper() * note, order is important - this must come before modes as -o attempts * to call UnOper. -- w00t */ - this->oper.clear(); + oper = NULL; /* Remove all oper only modes from the user when the deoper - Bug #466*/ diff --git a/src/whois.cpp b/src/whois.cpp index 290566446..1f21553c5 100644 --- a/src/whois.cpp +++ b/src/whois.cpp @@ -53,7 +53,7 @@ void InspIRCd::DoWhois(User* user, User* dest,unsigned long signon, unsigned lon if (this->Config->GenericOper) this->SendWhoisLine(user, dest, 313, "%s %s :is an IRC operator",user->nick.c_str(), dest->nick.c_str()); else - this->SendWhoisLine(user, dest, 313, "%s %s :is %s %s on %s",user->nick.c_str(), dest->nick.c_str(), (strchr("AEIOUaeiou",dest->oper[0]) ? "an" : "a"),irc::Spacify(dest->oper.c_str()), this->Config->Network.c_str()); + this->SendWhoisLine(user, dest, 313, "%s %s :is %s %s on %s",user->nick.c_str(), dest->nick.c_str(), (strchr("AEIOUaeiou",dest->oper->name[0]) ? "an" : "a"),dest->oper->NameStr(), this->Config->Network.c_str()); } if (user == dest || user->HasPrivPermission("users/auspex"))