diff options
-rw-r--r-- | conf/opers.conf.example | 3 | ||||
-rw-r--r-- | include/configreader.h | 12 | ||||
-rw-r--r-- | include/users.h | 3 | ||||
-rw-r--r-- | src/commands/cmd_notice.cpp | 5 | ||||
-rw-r--r-- | src/configreader.cpp | 10 | ||||
-rw-r--r-- | src/inspircd.cpp | 2 | ||||
-rw-r--r-- | src/users.cpp | 74 |
7 files changed, 93 insertions, 16 deletions
diff --git a/conf/opers.conf.example b/conf/opers.conf.example index c8bdc0a64..d1e317aad 100644 --- a/conf/opers.conf.example +++ b/conf/opers.conf.example @@ -17,6 +17,9 @@ # commands: oper commands that users of this class can run. commands="DIE RESTART REHASH LOADMODULE UNLOADMODULE RELOAD" + # privs: special priviledges that users with this class may utilise. +# privs="users/mass-message" + # usermodes: Oper-only usermodes that opers with this class can use. usermodes="*" diff --git a/include/configreader.h b/include/configreader.h index 41a0fc9b1..89116c5c5 100644 --- a/include/configreader.h +++ b/include/configreader.h @@ -232,13 +232,19 @@ struct operclass_data : public Extensible { /** Command list for the class */ - char* commandlist; + char *commandlist; + /** Channel mode list for the class */ - char* cmodelist; + char *cmodelist; + /** User mode list for the class */ - char* umodelist; + char *umodelist; + + /** Priviledges given by this class + */ + char *privs; }; /** A Set of oper classes diff --git a/include/users.h b/include/users.h index 2f8730088..d8a9b3e64 100644 --- a/include/users.h +++ b/include/users.h @@ -794,8 +794,9 @@ class CoreExport User : public EventHandler * all operators, yet are not commands. An example might be oper override, mass messaging (/notice $*), etc. * * @param privstr The priv to chec, e.g. "users/override/topic". These are loaded free-form from the config file. + * @param noisy If set to true, the user is notified that they do not have the specified permission where applicable. If false, no notification is sent. * @return True if this user has the permission in question. - */ bool HasPrivPermission(const std::string &privstr); + */ bool HasPrivPermission(const std::string &privstr, bool noisy = true); /** Returns true or false if a user can set a privileged user or channel mode. * This is done by looking up their oper type from User::oper, then referencing diff --git a/src/commands/cmd_notice.cpp b/src/commands/cmd_notice.cpp index 37f11eeb9..537f8ac78 100644 --- a/src/commands/cmd_notice.cpp +++ b/src/commands/cmd_notice.cpp @@ -30,8 +30,11 @@ CmdResult CommandNotice::Handle (const std::vector<std::string>& parameters, Use if (ServerInstance->Parser->LoopCall(user, this, parameters, 0)) return CMD_SUCCESS; - if ((parameters[0][0] == '$') && (IS_OPER(user) || ServerInstance->ULine(user->server))) + if (parameters[0][0] == '$') { + if (!user->HasPrivPermission("users/mass-message")) + return CMD_SUCCESS; + int MOD_RESULT = 0; std::string temp = parameters[1]; FOREACH_RESULT(I_OnUserPreNotice,OnUserPreNotice(user, (void*)parameters[0].c_str(), TYPE_SERVER, temp, 0, exempt_list)); diff --git a/src/configreader.cpp b/src/configreader.cpp index 118507861..189146137 100644 --- a/src/configreader.cpp +++ b/src/configreader.cpp @@ -913,9 +913,9 @@ void ServerConfig::Read(bool bail, const std::string &useruid) InitTypes, DoType, DoneClassesAndTypes}, {"class", - {"name", "commands", "usermodes", "chanmodes", NULL}, - {"", "", "", "", NULL}, - {DT_NOSPACES, DT_CHARPTR, DT_CHARPTR, DT_CHARPTR}, + {"name", "commands", "usermodes", "chanmodes", "privs", NULL}, + {"", "", "", "", "", NULL}, + {DT_NOSPACES, DT_CHARPTR, DT_CHARPTR, DT_CHARPTR, DT_CHARPTR}, InitClasses, DoClass, DoneClassesAndTypes}, {NULL, @@ -2224,6 +2224,8 @@ bool InitClasses(ServerConfig* conf, const char*) delete[] n->second.cmodelist; if (n->second.umodelist) delete[] n->second.umodelist; + if (n->second.privs) + delete[] n->second.privs; } } @@ -2252,6 +2254,7 @@ bool DoClass(ServerConfig* conf, const char* tag, char**, ValueList &values, int const char* CommandList = values[1].GetString(); const char* UModeList = values[2].GetString(); const char* CModeList = values[3].GetString(); + const char *PrivsList = values[4].GetString(); for (const char* c = UModeList; *c; ++c) { @@ -2271,6 +2274,7 @@ bool DoClass(ServerConfig* conf, const char* tag, char**, ValueList &values, int conf->operclass[ClassName].commandlist = strnewdup(CommandList); conf->operclass[ClassName].umodelist = strnewdup(UModeList); conf->operclass[ClassName].cmodelist = strnewdup(CModeList); + conf->operclass[ClassName].privs = strnewdup(PrivsList); return true; } diff --git a/src/inspircd.cpp b/src/inspircd.cpp index 3a2392ee6..463f9d82f 100644 --- a/src/inspircd.cpp +++ b/src/inspircd.cpp @@ -656,8 +656,6 @@ InspIRCd::InspIRCd(int argc, char** argv) /* set up fake client again this time with the correct uid */ this->FakeClient = new User(this, "#INVALID"); this->FakeClient->SetFd(FD_MAGIC_NUMBER); - this->FakeClient->HasPrivPermission("users/override/topic"); - exit(0); // Get XLine to do it's thing. this->XLines->CheckELines(); diff --git a/src/users.cpp b/src/users.cpp index 3b69c1a25..2b6e00e0e 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -216,7 +216,7 @@ User::User(InspIRCd* Instance, const std::string &uid) : ServerInstance(Instance Visibility = NULL; ip = NULL; MyClass = NULL; - AllowedOperCommands = NULL; + AllowedPrivs = AllowedOperCommands = NULL; chans.clear(); invites.clear(); @@ -242,12 +242,19 @@ User::~User() this->MyClass->RefCount--; ServerInstance->Logs->Log("USERS", DEBUG, "User destructor -- connect refcount now: %lu", this->MyClass->RefCount); } + if (this->AllowedOperCommands) { delete AllowedOperCommands; AllowedOperCommands = NULL; } + if (this->AllowedPrivs) + { + delete AllowedPrivs; + AllowedPrivs = NULL; + } + this->InvalidateCache(); this->DecrementModes(); @@ -505,10 +512,46 @@ bool User::HasPermission(const std::string &command) } -bool User::HasPrivPermission(const std::string &privstr) +bool User::HasPrivPermission(const std::string &privstr, bool noisy) { - ServerInstance->Logs->Log("CRAP", DEBUG, "Checking if I have " + privstr); - return true; + ServerInstance->Logs->Log("PRIVS", DEBUG, "Checking if I have " + privstr); + if (!IS_LOCAL(this)) + { + ServerInstance->Logs->Log("PRIVS", DEBUG, "Remote (yes)"); + return true; + } + + if (!IS_OPER(this)) + { + if (noisy) + this->WriteServ("NOTICE %s :You are not an oper", this->nick.c_str()); + ServerInstance->Logs->Log("PRIVS", DEBUG, "Not oper (no)"); + return false; + } + + if (!AllowedPrivs) + { + if (noisy) + this->WriteServ("NOTICE %s :Privset empty(!?)", this->nick.c_str()); + ServerInstance->Logs->Log("PRIVS", DEBUG, "No privs(?) (no)"); + return false; + } + + if (AllowedPrivs->find(privstr) != AllowedPrivs->end()) + { + ServerInstance->Logs->Log("PRIVS", DEBUG, "I do have it."); + return true; + } + else if (AllowedPrivs->find("*") != AllowedPrivs->end()) + { + ServerInstance->Logs->Log("PRIVS", DEBUG, "I allow all."); + return true; + } + + 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()); + ServerInstance->Logs->Log("PRIVS", DEBUG, "I don't have it..."); + return false; } bool User::AddBuffer(const std::string &a) @@ -717,28 +760,40 @@ void User::Oper(const std::string &opertype, const std::string &opername) opertype_t::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 (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. - std::string myclass, mycmd; + std::string myclass, mycmd, mypriv; irc::spacesepstream Classes(iter_opertype->second); while (Classes.GetToken(myclass)) { operclass_t::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.commandlist); while (CommandList.GetToken(mycmd)) { this->AllowedOperCommands->insert(mycmd); } + + irc::spacesepstream PrivList(iter_operclass->second.privs); + while (PrivList.GetToken(mypriv)) + { + this->AllowedPrivs->insert(mypriv); + } + for (unsigned char* c = (unsigned char*)iter_operclass->second.umodelist; *c; ++c) { if (*c == '*') @@ -750,6 +805,7 @@ void User::Oper(const std::string &opertype, const std::string &opername) this->AllowedUserModes[*c - 'A'] = true; } } + for (unsigned char* c = (unsigned char*)iter_operclass->second.cmodelist; *c; ++c) { if (*c == '*') @@ -804,6 +860,12 @@ void User::UnOper() AllowedOperCommands = NULL; } + if (AllowedPrivs) + { + delete AllowedPrivs; + AllowedPrivs = NULL; + } + AllowedUserModes.reset(); AllowedChanModes.reset(); } |