]> git.netwichtig.de Git - user/henk/code/inspircd.git/commitdiff
Add ability to control what opertypes can set what operonly user/chan modes. This...
authoraquanight <aquanight@e03df62e-2008-0410-955e-edbf42e46eb7>
Sun, 23 Mar 2008 20:43:35 +0000 (20:43 +0000)
committeraquanight <aquanight@e03df62e-2008-0410-955e-edbf42e46eb7>
Sun, 23 Mar 2008 20:43:35 +0000 (20:43 +0000)
git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@9176 e03df62e-2008-0410-955e-edbf42e46eb7

include/configreader.h
include/mode.h
include/users.h
src/configreader.cpp
src/mode.cpp
src/users.cpp

index 3120d3d59b69fb5267b9f3fc7eb5ef7a90b8ce50..b94687b43d4b40b3a1217e8c770f91e7ad7f6017 100644 (file)
@@ -203,9 +203,16 @@ struct MultiConfig
  */
 typedef std::map<irc::string,char*> opertype_t;
 
+struct operclass_data
+{
+       char* commandlist;
+       char* cmodelist;
+       char* umodelist;
+};
+
 /** A Set of oper classes
  */
-typedef std::map<irc::string,char*> operclass_t;
+typedef std::map<irc::string, operclass_data> operclass_t;
 
 
 /** This class holds the bulk of the runtime configuration for the ircd.
index ca610e46a0f28157dca75f3d57030d4ffb9f017f..f6022c0901e80a577e00e05578d6fcd66772cc11 100644 (file)
 #ifndef __MODE_H
 #define __MODE_H
 
+/* Forward declarations. */
+class User;
+
+#include "channels.h"
+
 /**
  * Holds the values for different type of modes
  * that can exist, USER or CHANNEL type.
index d1f61932e3b83f6d9264d95ebeb0622253d86efa..a12282ac92050b3e1a61556150348d5039432f32 100644 (file)
@@ -18,6 +18,8 @@
 #include "connection.h"
 #include "dns.h"
 
+#include "mode.h"
+
 /** Channel status for a user
  */
 enum ChanStatus {
@@ -455,6 +457,12 @@ class CoreExport User : public connection
 
        std::map<std::string, bool>* AllowedOperCommands;
 
+       /** Allowed user modes from oper classes. */
+       bool AllowedUserModes[64];
+
+       /** Allowed channel modes from oper classes. */
+       bool AllowedChanModes[64];
+
  public:
        /** Contains a pointer to the connect class a user is on from - this will be NULL for remote connections.
         * The pointer is guarenteed to *always* be valid. :)
@@ -755,6 +763,15 @@ class CoreExport User : public connection
         */
        bool HasPermission(const std::string &command);
 
+       /** 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
+        * this to their oper classes, and checking the modes they can set.
+        * @param mode The mode the check
+        * @param type ModeType (MODETYPE_CHANNEL or MODETYPE_USER).
+        * @return True if the user can set or unset this mode.
+        */
+       bool HasModePermission(unsigned char mode, ModeType type);
+
        /** Calls read() to read some data for this user using their fd.
         * @param buffer The buffer to read into
         * @param size The size of data to read
index 2093c82c8e313366c820347560cabbf46e8eb7c3..83b7e14d9bfbe34789da418f14e1f49f87759299 100644 (file)
@@ -925,9 +925,9 @@ void ServerConfig::Read(bool bail, User* user)
                                InitTypes, DoType, DoneClassesAndTypes},
 
                {"class",
-                               {"name",        "commands",     NULL},
-                               {"",            "",             NULL},
-                               {DT_NOSPACES,   DT_CHARPTR},
+                               {"name",        "commands",     "usermodes",    "chanmodes",    NULL},
+                               {"",            "",             "",             "",             NULL},
+                               {DT_NOSPACES,   DT_CHARPTR,     DT_CHARPTR,     DT_CHARPTR},
                                InitClasses, DoClass, DoneClassesAndTypes},
        
                {NULL,
@@ -2105,8 +2105,12 @@ bool InitClasses(ServerConfig* conf, const char*)
        {
                for (operclass_t::iterator n = conf->operclass.begin(); n != conf->operclass.end(); n++)
                {
-                       if (n->second)
-                               delete[] n->second;
+                       if (n->second.commandlist)
+                               delete[] n->second.commandlist;
+                       if (n->second.cmodelist)
+                               delete[] n->second.cmodelist;
+                       if (n->second.umodelist)
+                               delete[] n->second.umodelist;
                }
        }
 
@@ -2129,12 +2133,31 @@ bool DoType(ServerConfig* conf, const char*, char**, ValueList &values, int*)
 /*
  * XXX should this be in a class? -- w00t
  */
-bool DoClass(ServerConfig* conf, const char*, char**, ValueList &values, int*)
+bool DoClass(ServerConfig* conf, const char* tag, char**, ValueList &values, int*)
 {
        const char* ClassName = values[0].GetString();
        const char* CommandList = values[1].GetString();
+       const char* UModeList = values[2].GetString();
+       const char* CModeList = values[3].GetString();
+
+       for (const char* c = UModeList; *c; ++c)
+       {
+               if ((*c < 'A' || *c > 'z') && *c != '*')
+               {
+                       throw CoreException("Character " + std::string(1, *c) + " is not a valid mode in <class:usermodes>");
+               }
+       }
+       for (const char* c = CModeList; *c; ++c)
+       {
+               if ((*c < 'A' || *c > 'z') && *c != '*')
+               {
+                       throw CoreException("Character " + std::string(1, *c) + " is not a valid mode in <class:chanmodes>");
+               }
+       }
 
-       conf->operclass[ClassName] = strnewdup(CommandList);
+       conf->operclass[ClassName].commandlist = strnewdup(CommandList);
+       conf->operclass[ClassName].umodelist = strnewdup(UModeList);
+       conf->operclass[ClassName].cmodelist = strnewdup(CModeList);
        return true;
 }
 
index 21d7fa412ba7e3a047428e76429dfac6c0a5f5ee..db9641edbb77662b42c2479729d7926577152c9c 100644 (file)
@@ -577,10 +577,13 @@ void ModeParser::Process(const char* const* parameters, int pcnt, User *user, bo
                                                        /* It's an oper only mode, check if theyre an oper. If they arent,
                                                         * eat any parameter that  came with the mode, and continue to next
                                                         */
-                                                       if ((IS_LOCAL(user)) && (modehandlers[handler_id]->NeedsOper()) && (!IS_OPER(user)))
+                                                       if ((IS_LOCAL(user)) && (modehandlers[handler_id]->NeedsOper()) && (!user->HasModePermission(modehandlers[handler_id]->GetModeChar(), type)))
                                                        {
-                                                               user->WriteNumeric(481, "%s :Permission Denied - Only IRC operators may %sset %s mode %c", user->nick,
-                                                                               adding ? "" : "un", type == MODETYPE_CHANNEL ? "channel" : "user",
+                                                               user->WriteNumeric(481, "%s :Permission Denied - Oper type %s does not have access to %sset %s mode %c",
+                                                                               user->nick,
+                                                                               user->oper,
+                                                                               adding ? "" : "un",
+                                                                               type == MODETYPE_CHANNEL ? "channel" : "user",
                                                                                modehandlers[handler_id]->GetModeChar());
                                                                continue;
                                                        }
index 5724e9eab44e27b0db30a9b3d1014f96b8c67628..bdceba1f5038a7587df82004a0843dfadb8f595e 100644 (file)
@@ -194,6 +194,8 @@ User::User(InspIRCd* Instance, const std::string &uid) : ServerInstance(Instance
        ip = NULL;
        MyClass = NULL;
        AllowedOperCommands = NULL;
+       memset(AllowedUserModes, 0, sizeof(AllowedUserModes));
+       memset(AllowedChanModes, 0, sizeof(AllowedChanModes));
        chans.clear();
        invites.clear();
        memset(modes,0,sizeof(modes));
@@ -437,6 +439,18 @@ void User::RemoveInvite(const irc::string &channel)
        }
 }
 
+bool User::HasModePermission(unsigned char mode, ModeType type)
+{
+       if (!IS_LOCAL(this))
+               return true;
+
+       if (!IS_OPER(this))
+               return false;
+
+       return ((type == MODETYPE_USER ? AllowedUserModes : AllowedChanModes))[(mode - 'A')];
+       
+}
+
 bool User::HasPermission(const std::string &command)
 {
        /*
@@ -676,7 +690,7 @@ void User::Oper(const std::string &opertype, const std::string &opername)
                                operclass_t::iterator iter_operclass = ServerInstance->Config->operclass.find(myclass);
                                if (iter_operclass != ServerInstance->Config->operclass.end())
                                {
-                                       char* CommandList = strdup(iter_operclass->second);
+                                       char* CommandList = strdup(iter_operclass->second.commandlist);
                                        mycmd = strtok_r(CommandList," ",&savept2);
                                        while (mycmd)
                                        {
@@ -684,6 +698,29 @@ void User::Oper(const std::string &opertype, const std::string &opername)
                                                mycmd = strtok_r(NULL," ",&savept2);
                                        }
                                        free(CommandList);
+                                       this->AllowedUserModes['o' - 'A'] = true; // Call me paranoid if you want.
+                                       for (unsigned char* c = (unsigned char*)iter_operclass->second.umodelist; *c; ++c)
+                                       {
+                                               if (*c == '*')
+                                               {
+                                                       memset(this->AllowedUserModes, (int)(true), sizeof(this->AllowedUserModes));
+                                               }
+                                               else
+                                               {
+                                                       this->AllowedUserModes[*c - 'A'] = true;
+                                               }
+                                       }
+                                       for (unsigned char* c = (unsigned char*)iter_operclass->second.cmodelist; *c; ++c)
+                                       {
+                                               if (*c == '*')
+                                               {
+                                                       memset(this->AllowedChanModes, (int)(true), sizeof(this->AllowedChanModes));
+                                               }
+                                               else
+                                               {
+                                                       this->AllowedChanModes[*c - 'A'] = true;
+                                               }
+                                       }
                                }
                                myclass = strtok_r(NULL," ",&savept);
                        }