]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/modules/m_cloaking.cpp
Server::GetAdmin, Server::GetServerDescription, Server::GetNetworkName --- *REMOVED*
[user/henk/code/inspircd.git] / src / modules / m_cloaking.cpp
index c6595eb6cf0967c6fba281b43a2d5c6ec5c3c560..5a0e28bb5e94958432591e9d6d9aff7879a5fda8 100644 (file)
@@ -2,7 +2,7 @@
  *       | Inspire Internet Relay Chat Daemon |
  *       +------------------------------------+
  *
- *  Inspire is copyright (C) 2002-2004 ChatSpike-Dev.
+ *  InspIRCd is copyright (C) 2002-2006 ChatSpike-Dev.
  *                       E-mail:
  *                <brain@chatspike.net>
  *               <Craig@chatspike.net>
 // the server->server link, and all encoding of hosts is
 // done locally on the server by this module.
 
-#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include "inspircd_config.h"
+#ifdef HAS_STDINT
+#include <stdint.h>
+#endif
+#include "configreader.h"
+#include "inspircd.h"
 #include "users.h"
 #include "channels.h"
 #include "modules.h"
 
 /* $ModDesc: Provides masking of user hostnames */
 
+extern InspIRCd* ServerInstance;
 
 /* The four core functions - F1 is optimized somewhat */
 
 #define F4(x, y, z) (y ^ (x | ~z))
 #define MD5STEP(f,w,x,y,z,in,s) (w += f(x,y,z) + in, w = (w<<s | w>>(32-s)) + x)
 
-typedef unsigned long word32;
+#ifndef HAS_STDINT
+typedef unsigned int uint32_t;
+#endif
+
+typedef uint32_t word32; /* NOT unsigned long. We don't support 16 bit platforms, anyway. */
 typedef unsigned char byte;
 
-struct xMD5Context {
+class xMD5Context : public classbase
+{
+ public:
        word32 buf[4];
        word32 bytes[2];
        word32 in[16];
 };
 
-class ModuleCloaking : public Module
+class CloakUser : public ModeHandler
 {
- private:
-
-        Server *Srv;
-
+       Server* Srv;
+       std::string prefix;
+       word32 key1;
+       word32 key2;
+       word32 key3;
+       word32 key4;
+       
        void byteSwap(word32 *buf, unsigned words)
        {
                byte *p = (byte *)buf;
        
-               do {
+               do
+               {
                        *buf++ = (word32)((unsigned)p[3] << 8 | p[2]) << 16 |
                                ((unsigned)p[1] << 8 | p[0]);
                        p += 4;
@@ -71,10 +91,10 @@ class ModuleCloaking : public Module
 
        void xMD5Init(struct xMD5Context *ctx)
        {
-               ctx->buf[0] = 0x67452301;
-               ctx->buf[1] = 0xefcdab89;
-               ctx->buf[2] = 0x98badcfe;
-               ctx->buf[3] = 0x10325476;
+               ctx->buf[0] = key1;
+               ctx->buf[1] = key2;
+               ctx->buf[2] = key3;
+               ctx->buf[3] = key4;
 
                ctx->bytes[0] = 0;
                ctx->bytes[1] = 0;
@@ -91,7 +111,8 @@ class ModuleCloaking : public Module
                        ctx->bytes[1]++;        /* Carry from low to high */
 
                t = 64 - (t & 0x3f);    /* Space available in ctx->in (at least 1) */
-               if ((unsigned)t > (unsigned)len) {
+               if ((unsigned)t > (unsigned)len)
+               {
                        memcpy((byte *)ctx->in + 64 - (unsigned)t, buf, len);
                        return;
                }
@@ -103,7 +124,8 @@ class ModuleCloaking : public Module
                len -= (unsigned)t;
 
                /* Process data in 64-byte chunks */
-               while (len >= 64) {
+               while (len >= 64)
+               {
                        memcpy(ctx->in, buf, 64);
                        byteSwap(ctx->in, 16);
                        xMD5Transform(ctx->buf, ctx->in);
@@ -126,7 +148,8 @@ class ModuleCloaking : public Module
                /* Bytes of padding needed to make 56 bytes (-8..55) */
                count = 56 - 1 - count;
 
-               if (count < 0) {        /* Padding forces an extra block */
+               if (count < 0)
+               {       /* Padding forces an extra block */
                        memset(p, 0, count+8);
                        byteSwap(ctx->in, 16);
                        xMD5Transform(ctx->buf, ctx->in);
@@ -247,7 +270,7 @@ class ModuleCloaking : public Module
                int i = 0;
                unsigned char bytes[16];
                char hash[MAXBUF];
-               strcpy(hash,"");
+               *hash = 0;
                MyMD5((char*)bytes,src,strlen(src));
                for (i = 0; i < 16; i++)
                {
@@ -260,110 +283,157 @@ class ModuleCloaking : public Module
                }
                strlcpy(dest,hash,MAXBUF);
        }
-        
+       
  public:
-       ModuleCloaking()
+       CloakUser(Server* Me) : ModeHandler('x', 0, 0, false, MODETYPE_USER, false), Srv(Me) { }
+
+       ModeAction OnModeChange(userrec* source, userrec* dest, chanrec* channel, std::string &parameter, bool adding)
        {
-               // We must create an instance of the Server class to work with
-               Srv = new Server;
-               
-               // we must create a new mode. Set the parameters so the
-               // mode doesn't require oper, and is a client usermode
-               // with no parameters (actually, you cant have params for a umode!)
-               if (!Srv->AddExtendedMode('x',MT_CLIENT,false,0,0))
+               /* Only opers can change other users modes */
+               if ((source != dest) && (!*source->oper))
+                       return MODEACTION_DENY;
+
+               /* For remote clients, we dont take any action, we just allow it.
+                * The local server where they are will set their cloak instead.
+                */
+               if (!IS_LOCAL(dest))
+                       return MODEACTION_ALLOW;
+
+               if (adding)
                {
-                       // we couldn't claim mode x... possibly anther module has it,
-                       // this might become likely to happen if there are a lot of 3rd
-                       // party modules around in the future -- any 3rd party modules
-                       // SHOULD implement a system of configurable mode letters (e.g.
-                       // from a config file)
-                       Srv->Log(DEFAULT,"*** m_cloaking: ERROR, failed to allocate user mode +x!");
-                       printf("Could not claim usermode +x for this module!");
-                       return;
-               }
-       }
-       
-       virtual ~ModuleCloaking()
-       {
-               // not really neccessary, but free it anyway
-               delete Srv;
-       }
-       
-       virtual Version GetVersion()
-       {
-               // returns the version number of the module to be
-               // listed in /MODULES
-               return Version(1,0,0,1,VF_STATIC|VF_VENDOR);
-       }
-       
-       virtual int OnExtendedMode(userrec* user, void* target, char modechar, int type, bool mode_on, string_list &params)
-       {
-               // this method is called for any extended mode character.
-               // all module modes for all modules pass through here
-               // (unless another module further up the chain claims them)
-               // so we must be VERY careful to only act upon modes which
-               // we have claimed ourselves. This is a feature to allow
-               // modules to 'spy' on extended mode activity if they so wish.
-               if ((modechar == 'x') && (type == MT_CLIENT))
-               {
-                       // OnExtendedMode gives us a void* as the target, we must cast
-                       // it into a userrec* or a chanrec* depending on the value of
-                       // the 'type' parameter (MT_CLIENT or MT_CHANNEL)
-                       userrec* dest = (userrec*)target;
-                       
-                       // we've now determined that this is our mode character...
-                       // is the user adding the mode to their list or removing it?
-                       if (mode_on)
+                       if(!dest->IsModeSet('x'))
                        {
-                               // the mode is being turned on - so attempt to
-                               // allocate the user a cloaked host using a non-reversible
-                               // algorithm (its simple, but its non-reversible so the
-                               // simplicity doesnt really matter). This algorithm
-                               // will not work if the user has only one level of domain
-                               // naming in their hostname (e.g. if they are on a lan or
-                               // are connecting via localhost) -- this doesnt matter much.
-                               if (strchr(dest->host,'.'))
+                               /* The mode is being turned on - so attempt to
+                                * allocate the user a cloaked host using a non-reversible
+                                * algorithm (its simple, but its non-reversible so the
+                                * simplicity doesnt really matter). This algorithm
+                                * will not work if the user has only one level of domain
+                                * naming in their hostname (e.g. if they are on a lan or
+                                * are connecting via localhost) -- this doesnt matter much.
+                                */
+                       
+                               if (strchr(dest->host,'.') || strchr(dest->host,':'))
                                {
-                                       // in inspircd users have two hostnames. A displayed
-                                       // hostname which can be modified by modules (e.g.
-                                       // to create vhosts, implement chghost, etc) and a
-                                       // 'real' hostname which you shouldnt write to.
-                                       std::string a = strstr(dest->host,".");
+                                       /* InspIRCd users have two hostnames; A displayed
+                                        * hostname which can be modified by modules (e.g.
+                                        * to create vhosts, implement chghost, etc) and a
+                                        * 'real' hostname which you shouldnt write to.
+                                        */
+
+                                       char* n = strstr(dest->host,".");
+                                       if (!n)
+                                               n = strstr(dest->host,":");
+
+                                       std::string a = n;
+                                       
                                        char ra[64];
                                        this->GenHash(dest->host,ra);
                                        std::string b = "";
-                                       in_addr testaddr;
-                                       if (!inet_aton(dest->host,&testaddr))
+                                       insp_inaddr testaddr;
+                                       std::string hostcloak = prefix + "-" + std::string(ra) + a;
+                               
+                                       /* Fix by brain - if the cloaked host is > the max length of a host (64 bytes
+                                        * according to the DNS RFC) then tough titty, they get cloaked as an IP. 
+                                        * Their ISP shouldnt go to town on subdomains, or they shouldnt have a kiddie
+                                        * vhost.
+                                        */
+
+                                       if ((insp_aton(dest->host,&testaddr) < 1) && (hostcloak.length() < 64))
                                        {
                                                // if they have a hostname, make something appropriate
-                                               b = Srv->GetNetworkName() + "-" + std::string(ra) + a;
+                                               b = hostcloak;
                                        }
                                        else
                                        {
                                                // else, they have an ip
-                                               b = std::string(ra) + "." + Srv->GetNetworkName() + ".cloak";
+                                               b = std::string(ra) + "." + prefix + ".cloak";
                                        }
                                        Srv->Log(DEBUG,"cloak: allocated "+b);
-                                       Srv->ChangeHost(dest,b);
+                                       dest->ChangeDisplayedHost(b.c_str());
                                }
+                               
+                               dest->SetMode('x',true);
+                               return MODEACTION_ALLOW;
                        }
-                       else
-                       {
-                               // user is removing the mode, so just restore their real host
-                               // and make it match the displayed one.
-                               Srv->ChangeHost(dest,dest->host);
-                       }
-                       // this mode IS ours, and we have handled it. If we chose not to handle it,
-                       // for example the user cannot cloak as they have a vhost or such, then
-                       // we could return 0 here instead of 1 and the core would not send the mode
-                       // change to the user.
-                       return 1;
                }
                else
+               {
+                       if (dest->IsModeSet('x'))
+                       {
+                               /* User is removing the mode, so just restore their real host
+                                * and make it match the displayed one.
+                                */
+                               dest->ChangeDisplayedHost(dest->host);
+                               dest->SetMode('x',false);
+                               return MODEACTION_ALLOW;
+                       }
+               }
+
+               return MODEACTION_DENY;
+       }
+       
+       void DoRehash()
+       {
+               ConfigReader Conf;
+               key1 = key2 = key3 = key4 = 0;
+               key1 = Conf.ReadInteger("cloak","key1",0,false);
+               key2 = Conf.ReadInteger("cloak","key2",0,false);
+               key3 = Conf.ReadInteger("cloak","key3",0,false);
+               key4 = Conf.ReadInteger("cloak","key4",0,false);
+               
+               prefix = Conf.ReadValue("cloak","prefix",0);
+               if (prefix == "")
                {
-                       // this mode isn't ours, we have to bail and return 0 to not handle it.
-                       return 0;
+                       prefix = ServerInstance->Config->Network;
                }
+               if (!key1 && !key2 && !key3 && !key4)
+               {
+                       ModuleException ex("You have not defined cloak keys for m_cloaking!!! THIS IS INSECURE AND SHOULD BE CHECKED!");
+                       throw (ex);
+               }
+       }
+};
+
+
+class ModuleCloaking : public Module
+{
+ private:
+       Server *Srv;
+       CloakUser* cu;
+
+ public:
+       ModuleCloaking(Server* Me)
+       : Module::Module(Me), Srv(Me)
+       {
+               /* Create new mode handler object */
+               cu = new CloakUser(Srv);
+
+               /* Register it with the core */         
+               Srv->AddMode(cu, 'x');
+
+               OnRehash("");
+       }
+       
+       virtual ~ModuleCloaking()
+       {
+               DELETE(cu);
+       }
+       
+       virtual Version GetVersion()
+       {
+               // returns the version number of the module to be
+               // listed in /MODULES
+               return Version(1,0,0,2,VF_STATIC|VF_VENDOR);
+       }
+
+       virtual void OnRehash(const std::string &parameter)
+       {
+               cu->DoRehash();
+       }
+
+       void Implements(char* List)
+       {
+               List[I_OnRehash] = List[I_OnUserConnect] = 1;
        }
 
        virtual void OnUserConnect(userrec* user)
@@ -374,7 +444,7 @@ class ModuleCloaking : public Module
                // SAMODE in unreal. Note that to the user it will appear as if they set
                // the mode on themselves.
                
-               char* modes[2];                 // only two parameters
+               const char* modes[2];           // only two parameters
                modes[0] = user->nick;          // first parameter is the nick
                modes[1] = "+x";                // second parameter is the mode
                Srv->SendMode(modes,2,user);    // send these, forming the command "MODE <nick> +x"
@@ -395,9 +465,9 @@ class ModuleCloakingFactory : public ModuleFactory
        {
        }
        
-       virtual Module * CreateModule()
+       virtual Module * CreateModule(Server* Me)
        {
-               return new ModuleCloaking;
+               return new ModuleCloaking(Me);
        }
        
 };
@@ -407,4 +477,3 @@ extern "C" void * init_module( void )
 {
        return new ModuleCloakingFactory;
 }
-