]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/modules/m_pbkdf2.cpp
Fix the cloaking module on C++98 compilers.
[user/henk/code/inspircd.git] / src / modules / m_pbkdf2.cpp
index b66b3f05891fa972943ed8c2823cb4f2555212e7..daafa7f8c72e9fc8de2275de03d17905522b5576 100644 (file)
@@ -1,7 +1,10 @@
 /*
  * InspIRCd -- Internet Relay Chat Daemon
  *
- *   Copyright (C) 2014 Daniel Vassdal <shutter@canternet.org>
+ *   Copyright (C) 2018, 2020 Sadie Powell <sadie@witchery.services>
+ *   Copyright (C) 2018 linuxdaemon <linuxdaemon.irc@gmail.com>
+ *   Copyright (C) 2014, 2020 Daniel Vassdal <shutter@canternet.org>
+ *   Copyright (C) 2014, 2016 Attila Molnar <attilamolnar@hush.com>
  *
  * This file is part of InspIRCd.  InspIRCd is free software: you can
  * redistribute it and/or modify it under the terms of the GNU General Public
@@ -43,7 +46,7 @@ class PBKDF2Hash
                std::string tok;
 
                ss.GetToken(tok);
-               this->iterations = ConvToInt(tok);
+               this->iterations = ConvToNum<unsigned int>(tok);
 
                ss.GetToken(tok);
                this->hash = Base64ToBin(tok);
@@ -81,24 +84,26 @@ class PBKDF2Provider : public HashProvider
                size_t blocks = std::ceil((double)dkl / provider->out_size);
 
                std::string output;
+               std::string tmphash;
+               std::string salt_block = salt;
                for (size_t block = 1; block <= blocks; block++)
                {
                        char salt_data[4];
                        for (size_t i = 0; i < sizeof(salt_data); i++)
                                salt_data[i] = block >> (24 - i * 8) & 0x0F;
 
-                       std::string salt_block(salt_data, 4);
-                       salt_block = salt + salt_block;
+                       salt_block.erase(salt.length());
+                       salt_block.append(salt_data, sizeof(salt_data));
 
                        std::string blockdata = provider->hmac(pass, salt_block);
                        std::string lasthash = blockdata;
                        for (size_t iter = 1; iter < itr; iter++)
                        {
-                               std::string tmphash = provider->hmac(pass, lasthash);
+                               tmphash = provider->hmac(pass, lasthash);
                                for (size_t i = 0; i < provider->out_size; i++)
                                        blockdata[i] ^= tmphash[i];
 
-                               lasthash = tmphash;
+                               lasthash.swap(tmphash);
                        }
                        output += blockdata;
                }
@@ -121,7 +126,7 @@ class PBKDF2Provider : public HashProvider
                        return false;
 
                std::string cmp = PBKDF2(input, hs.salt, hs.iterations, hs.length);
-               return (cmp == hs.hash);
+               return InspIRCd::TimingSafeCompare(cmp, hs.hash);
        }
 
        std::string ToPrintable(const std::string& raw) CXX11_OVERRIDE
@@ -137,39 +142,65 @@ class PBKDF2Provider : public HashProvider
        }
 };
 
+struct ProviderConfig
+{
+       unsigned long dkey_length;
+       unsigned long iterations;
+};
+
+typedef std::map<std::string, ProviderConfig> ProviderConfigMap;
+
 class ModulePBKDF2 : public Module
 {
        std::vector<PBKDF2Provider*> providers;
+       ProviderConfig globalconfig;
+       ProviderConfigMap providerconfigs;
 
-       void GetConfig()
+       ProviderConfig GetConfigForProvider(const std::string& name) const
+       {
+               ProviderConfigMap::const_iterator it = providerconfigs.find(name);
+               if (it == providerconfigs.end())
+                       return globalconfig;
+
+               return it->second;
+       }
+
+       void ConfigureProviders()
        {
-               // First set the common values
-               ConfigTag* tag = ServerInstance->Config->ConfValue("pbkdf2");
-               unsigned int global_iterations = tag->getInt("iterations", 12288, 1);
-               unsigned int global_dkey_length = tag->getInt("length", 32, 1, 1024);
                for (std::vector<PBKDF2Provider*>::iterator i = providers.begin(); i != providers.end(); ++i)
                {
                        PBKDF2Provider* pi = *i;
-                       pi->iterations = global_iterations;
-                       pi->dkey_length = global_dkey_length;
+                       ProviderConfig config = GetConfigForProvider(pi->name);
+                       pi->iterations = config.iterations;
+                       pi->dkey_length = config.dkey_length;
                }
+       }
+
+       void GetConfig()
+       {
+               // First set the common values
+               ConfigTag* tag = ServerInstance->Config->ConfValue("pbkdf2");
+               ProviderConfig newglobal;
+               newglobal.iterations = tag->getUInt("iterations", 12288, 1);
+               newglobal.dkey_length = tag->getUInt("length", 32, 1, 1024);
 
                // Then the specific values
+               ProviderConfigMap newconfigs;
                ConfigTagList tags = ServerInstance->Config->ConfTags("pbkdf2prov");
                for (ConfigIter i = tags.first; i != tags.second; ++i)
                {
                        tag = i->second;
                        std::string hash_name = "hash/" + tag->getString("hash");
-                       for (std::vector<PBKDF2Provider*>::iterator j = providers.begin(); j != providers.end(); ++j)
-                       {
-                               PBKDF2Provider* pi = *j;
-                               if (pi->provider->name != hash_name)
-                                       continue;
+                       ProviderConfig& config = newconfigs[hash_name];
 
-                               pi->iterations = tag->getInt("iterations", global_iterations, 1);
-                               pi->dkey_length = tag->getInt("length", global_dkey_length, 1, 1024);
-                       }
+                       config.iterations = tag->getUInt("iterations", newglobal.iterations, 1);
+                       config.dkey_length = tag->getUInt("length", newglobal.dkey_length, 1, 1024);
                }
+
+               // Config is valid, apply it
+               providerconfigs.swap(newconfigs);
+               std::swap(globalconfig, newglobal);
+               ConfigureProviders();
        }
 
  public:
@@ -178,71 +209,43 @@ class ModulePBKDF2 : public Module
                stdalgo::delete_all(providers);
        }
 
-       void Prioritize() CXX11_OVERRIDE
+       void init() CXX11_OVERRIDE
        {
-               OnLoadModule(NULL);
+               // Let ourself know about any existing services.
+               const ModuleManager::DataProviderMap& dataproviders = ServerInstance->Modules->DataProviders;
+               for (ModuleManager::DataProviderMap::const_iterator it = dataproviders.begin(); it != dataproviders.end(); ++it)
+                       OnServiceAdd(*it->second);
        }
 
-       void OnLoadModule(Module* mod) CXX11_OVERRIDE
+       void OnServiceAdd(ServiceProvider& provider) CXX11_OVERRIDE
        {
-               bool newProv = false;
-               // As the module doesn't tell us what ServiceProviders it has, let's iterate all (yay ...) the ServiceProviders
-               // Good thing people don't run loading and unloading those all the time
-               for (std::multimap<std::string, ServiceProvider*>::iterator i = ServerInstance->Modules->DataProviders.begin(); i != ServerInstance->Modules->DataProviders.end(); ++i)
-               {
-                       ServiceProvider* provider = i->second;
-
-                       // Does the service belong to the new mod?
-                       // In the case this is our first run (mod == NULL, continue anyway)
-                       if (mod && provider->creator != mod)
-                               continue;
-
-                       // Check if it's a hash provider
-                       if (provider->name.compare(0, 5, "hash/"))
-                               continue;
-
-                       HashProvider* hp = static_cast<HashProvider*>(provider);
-
-                       if (hp->IsKDF())
-                               continue;
+               // Check if it's a hash provider
+               if (provider.name.compare(0, 5, "hash/"))
+                       return;
 
-                       bool has_prov = false;
-                       for (std::vector<PBKDF2Provider*>::const_iterator j = providers.begin(); j != providers.end(); ++j)
-                       {
-                               if ((*j)->provider == hp)
-                               {
-                                       has_prov = true;
-                                       break;
-                               }
-                       }
-                       if (has_prov)
-                               continue;
+               HashProvider* hp = static_cast<HashProvider*>(&provider);
+               if (hp->IsKDF())
+                       return;
 
-                       newProv = true;
+               PBKDF2Provider* prov = new PBKDF2Provider(this, hp);
+               providers.push_back(prov);
+               ServerInstance->Modules.AddService(*prov);
 
-                       PBKDF2Provider* prov = new PBKDF2Provider(this, hp);
-                       providers.push_back(prov);
-                       ServerInstance->Modules->AddService(*prov);
-               }
-
-               if (newProv)
-                       GetConfig();
+               ConfigureProviders();
        }
 
-       void OnUnloadModule(Module* mod) CXX11_OVERRIDE
+       void OnServiceDel(ServiceProvider& prov) CXX11_OVERRIDE
        {
-               for (std::vector<PBKDF2Provider*>::iterator i = providers.begin(); i != providers.end(); )
+               for (std::vector<PBKDF2Provider*>::iterator i = providers.begin(); i != providers.end(); ++i)
                {
                        PBKDF2Provider* item = *i;
-                       if (item->provider->creator != mod)
-                       {
-                               ++i;
+                       if (item->provider != &prov)
                                continue;
-                       }
 
                        ServerInstance->Modules->DelService(*item);
                        delete item;
-                       i = providers.erase(i);
+                       providers.erase(i);
+                       break;
                }
        }
 
@@ -253,7 +256,7 @@ class ModulePBKDF2 : public Module
 
        Version GetVersion() CXX11_OVERRIDE
        {
-               return Version("Implements PBKDF2 hashing", VF_VENDOR);
+               return Version("Allows other modules to generate PBKDF2 hashes.", VF_VENDOR);
        }
 };