summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/configreader.h35
-rw-r--r--include/users.h11
-rw-r--r--src/command_parse.cpp3
-rw-r--r--src/commands/cmd_oper.cpp108
-rw-r--r--src/configreader.cpp49
-rw-r--r--src/mode.cpp2
-rw-r--r--src/modes/umode_o.cpp2
-rw-r--r--src/modules/m_check.cpp2
-rw-r--r--src/modules/m_httpd_stats.cpp2
-rw-r--r--src/modules/m_operchans.cpp2
-rw-r--r--src/modules/m_operjoin.cpp2
-rw-r--r--src/modules/m_operlevels.cpp12
-rw-r--r--src/modules/m_opermodes.cpp5
-rw-r--r--src/modules/m_override.cpp2
-rw-r--r--src/modules/m_spanningtree/netburst.cpp2
-rw-r--r--src/modules/m_spanningtree/opertype.cpp9
-rw-r--r--src/modules/m_sqloper.cpp27
-rw-r--r--src/modules/m_swhois.cpp27
-rw-r--r--src/users.cpp128
-rw-r--r--src/whois.cpp2
20 files changed, 205 insertions, 227 deletions
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<std::string, reference<ConfigTag> > ConfigDataHash;
-typedef std::map<std::string, reference<ConfigTag> > 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:
+ /** <oper> block used for this oper-up. May be NULL. */
+ reference<ConfigTag> oper_block;
+ /** <type> block used for this oper-up. Valid for local users, may be NULL on remote */
+ reference<ConfigTag> type_block;
+ /** <class> blocks referenced from the <type> block. These define individual permissions */
+ std::vector<reference<ConfigTag> > 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<std::string, reference<ConfigTag> > TagIndex;
+typedef std::map<std::string, reference<OperInfo> > 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 &lt;connect allow&gt; and &lt;connect deny&gt; 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<OperInfo> 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<FakeUser*>(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<std::string>& 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<std::string>& 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<std::string, ConfigTag*> 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("<type:name> is missing from tag at " + tag->getTagLocation());
- opertypes[name] = tag;
+
+ if (!ServerInstance->IsNick(name.c_str(), Limits.NickMax))
+ throw CoreException("<type:name> 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("<oper:name> 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 << "<away>" << Sanitize(u->awaymsg) << "</away><awaytime>" << u->awaytime << "</awaytime>";
if (IS_OPER(u))
- data << "<opertype>" << Sanitize(u->oper) << "</opertype>";
+ data << "<opertype>" << Sanitize(u->oper->NameStr()) << "</opertype>";
data << "<modes>" << u->FormatModes() << "</modes><ident>" << Sanitize(u->ident) << "</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<std::string, std::vector<std::string> >::iterator i = operTypeChans.find(user->oper);
+ std::map<std::string, std::vector<std::string> >::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 <type:modes>,
// 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 <type:override>
- 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 &params)
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<std::string>;
+ if (AllowedOperCommands)
+ AllowedOperCommands->clear();
+ else
+ AllowedOperCommands = new std::set<std::string>;
- if (AllowedPrivs)
- AllowedPrivs->clear();
- else
- AllowedPrivs = new std::set<std::string>;
+ if (AllowedPrivs)
+ AllowedPrivs->clear();
+ else
+ AllowedPrivs = new std::set<std::string>;
- 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<reference<ConfigTag> >::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"))