diff options
author | Peter Powell <petpow@saberuk.com> | 2016-04-13 20:26:50 +0100 |
---|---|---|
committer | Peter Powell <petpow@saberuk.com> | 2016-04-13 20:26:50 +0100 |
commit | f4f6787c9ccdbcb675e0c81129abce469f694d94 (patch) | |
tree | 43391b25121c696e1ae5f507432fe71a9501ec2f | |
parent | 79e7c3f98a57b7cffc46d9a7dc250a0e6e25fc98 (diff) |
Remove support for DH-AES and DH-BLOWFISH.
These SASL mechanisms are considered insecure and should not be
used anymore.
-rw-r--r-- | data/modules.example.conf | 18 | ||||
-rw-r--r-- | modules/extra/m_sasl_dh-aes.cpp | 193 | ||||
-rw-r--r-- | modules/extra/m_sasl_dh-blowfish.cpp | 203 |
3 files changed, 0 insertions, 414 deletions
diff --git a/data/modules.example.conf b/data/modules.example.conf index 7e1a4eca5..e921c1e0d 100644 --- a/data/modules.example.conf +++ b/data/modules.example.conf @@ -543,24 +543,6 @@ module { name = "help" } #module { name = "m_sasl" } /* - * m_sasl_dh-aes [EXTRA] - * - * Add the DH-AES mechanism to SASL. - * Requires m_sasl to be loaded. - * Requires openssl. - */ -#module { name = "m_sasl_dh-aes" } - -/* - * m_sasl_dh-blowfish [EXTRA] - * - * Add the DH-BLOWFISH mechanism to SASL. - * Requires m_sasl to be loaded. - * Requires openssl. - */ -#module { name = "m_sasl_dh-blowfish" } - -/* * m_ssl_gnutls [EXTRA] * * This module provides SSL services to Anope using GnuTLS, for example to diff --git a/modules/extra/m_sasl_dh-aes.cpp b/modules/extra/m_sasl_dh-aes.cpp deleted file mode 100644 index a7138ec55..000000000 --- a/modules/extra/m_sasl_dh-aes.cpp +++ /dev/null @@ -1,193 +0,0 @@ -/* - * - * (C) 2014 Daniel Vassdal <shutter@canternet.org> - * (C) 2014-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - */ - -/* RequiredLibraries: ssl,crypto */ -/* RequiredWindowsLibraries: ssleay32,libeay32 */ - -#include "module.h" -#include "modules/sasl.h" - -#include <openssl/bn.h> -#include <openssl/dh.h> -#include <openssl/aes.h> - -using namespace SASL; - -class DHAES : public Mechanism -{ - void Err(Session* sess, BIGNUM* key = NULL) - { - if (key) - BN_free(key); - - sasl->Fail(sess); - delete sess; - } - - public: - struct DHAESSession : SASL::Session - { - DH* dh; - DHAESSession(Mechanism *m, const Anope::string &u, DH* dh_params) : SASL::Session(m, u) - { - if (!(dh = DH_new())) - return; - - dh->g = BN_dup(dh_params->g); - dh->p = BN_dup(dh_params->p); - - if (!DH_generate_key(dh)) - { - DH_free(dh); - dh = NULL; - } - } - - ~DHAESSession() - { - if (dh) - DH_free(dh); - } - }; - - DH* dh_params; - const size_t keysize; - SASL::Session* CreateSession(const Anope::string &uid) anope_override - { - return new DHAESSession(this, uid, dh_params); - } - - DHAES(Module *o) : Mechanism(o, "DH-AES"), keysize(256 / 8) - { - if (!(dh_params = DH_new())) - throw ModuleException("DH_new() failed!"); - - if (!DH_generate_parameters_ex(dh_params, keysize * 8, 5, NULL)) - { - DH_free(dh_params); - throw ModuleException("Could not generate DH-params"); - } - } - - ~DHAES() - { - DH_free(dh_params); - } - - void ProcessMessage(SASL::Session *session, const SASL::Message &m) anope_override - { - DHAESSession *sess = anope_dynamic_static_cast<DHAESSession *>(session); - - if (!sess->dh) - { - sasl->SendMessage(sess, "D", "A"); - delete sess; - return; - } - - if (m.type == "S") - { - // Format: [ss]<p>[ss]<g>[ss]<pub_key> - // Where ss is a unsigned short with the size of the key - const BIGNUM* dhval[] = { sess->dh->p, sess->dh->g, sess->dh->pub_key }; - - // Find the size of our buffer - initialized at 6 because of string size data - size_t size = 6; - for (size_t i = 0; i < 3; i++) - size += BN_num_bytes(dhval[i]); - - // Fill in the DH data - std::vector<unsigned char> buffer(size); - for (size_t i = 0, pos = 0; i < 3; i++) - { - *reinterpret_cast<uint16_t*>(&buffer[pos]) = htons(BN_num_bytes(dhval[i])); - pos += 2; - BN_bn2bin(dhval[i], &buffer[pos]); - pos += BN_num_bytes(dhval[i]); - } - - Anope::string encoded; - Anope::B64Encode(Anope::string(buffer.begin(), buffer.end()), encoded); - sasl->SendMessage(sess, "C", encoded); - } - else if (m.type == "C") - { - // Make sure we have some data - actual size check is done later - if (m.data.length() < 10) - return Err(sess); - - // Format: [ss]<key>[ss]<iv>[ss]<encrypted> - // <encrypted> = <username>\0<password>\0 - - Anope::string decoded; - Anope::B64Decode(m.data, decoded); - - // Make sure we have an IV and at least one encrypted block - if ((decoded.length() < keysize + 2 + (AES_BLOCK_SIZE * 2)) || ((decoded.length() - keysize - 2) % AES_BLOCK_SIZE)) - return Err(sess); - - const unsigned char* data = reinterpret_cast<const unsigned char*>(decoded.data()); - - // Control the size of the key - if (ntohs(*reinterpret_cast<const uint16_t*>(&data[0])) != keysize) - return Err(sess); - - // Convert pubkey from binary - size_t pos = 2; - BIGNUM* pubkey = BN_bin2bn(&data[pos], keysize, NULL); - if (!pubkey) - return Err(sess); - - // Find shared key - std::vector<unsigned char> secretkey(keysize); - if (DH_compute_key(&secretkey[0], pubkey, sess->dh) != static_cast<int>(keysize)) - return Err(sess, pubkey); - - // Set decryption key - AES_KEY AESKey; - AES_set_decrypt_key(&secretkey[0], keysize * 8, &AESKey); - - // Fetch IV - pos += keysize; - std::vector<unsigned char> IV(data + pos, data + pos + AES_BLOCK_SIZE); - - // Find encrypted blocks, and decrypt - pos += AES_BLOCK_SIZE; - size_t size = decoded.length() - pos; - std::vector<char> decrypted(size + 2, 0); - AES_cbc_encrypt(&data[pos], reinterpret_cast<unsigned char*>(&decrypted[0]), size, &AESKey, &IV[0], AES_DECRYPT); - - std::string username = &decrypted[0]; - std::string password = &decrypted[username.length() + 1]; - - if (username.empty() || password.empty() || !IRCD->IsNickValid(username) || password.find_first_of("\r\n") != Anope::string::npos) - return Err(sess, pubkey); - - SASL::IdentifyRequest* req = new SASL::IdentifyRequest(this->owner, m.source, username, password); - FOREACH_MOD(OnCheckAuthentication, (NULL, req)); - req->Dispatch(); - - BN_free(pubkey); - } - } -}; - - -class ModuleSASLDHAES : public Module -{ - DHAES dhaes; - - public: - ModuleSASLDHAES(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR | EXTRA), - dhaes(this) - { - } -}; - -MODULE_INIT(ModuleSASLDHAES) diff --git a/modules/extra/m_sasl_dh-blowfish.cpp b/modules/extra/m_sasl_dh-blowfish.cpp deleted file mode 100644 index 84b05d559..000000000 --- a/modules/extra/m_sasl_dh-blowfish.cpp +++ /dev/null @@ -1,203 +0,0 @@ -/* - * - * (C) 2014 Daniel Vassdal <shutter@canternet.org> - * (C) 2011-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - */ - -/* RequiredLibraries: ssl,crypto */ -/* RequiredWindowsLibraries: ssleay32,libeay32 */ - -#include "module.h" -#include "modules/sasl.h" - -#include <openssl/bn.h> -#include <openssl/dh.h> -#include <openssl/blowfish.h> - -using namespace SASL; - -class DHBS : public Mechanism -{ - void Err(Session* sess, BIGNUM* key = NULL) - { - if (key) - BN_free(key); - - sasl->Fail(sess); - delete sess; - } - - public: - struct DHBSSession : SASL::Session - { - DH* dh; - DHBSSession(Mechanism *m, const Anope::string &u, DH* dh_params) : SASL::Session(m, u) - { - if (!(dh = DH_new())) - return; - - dh->g = BN_dup(dh_params->g); - dh->p = BN_dup(dh_params->p); - - if (!DH_generate_key(dh)) - { - DH_free(dh); - dh = NULL; - } - } - - ~DHBSSession() - { - if (dh) - DH_free(dh); - } - }; - - DH* dh_params; - const size_t keysize; - SASL::Session* CreateSession(const Anope::string &uid) anope_override - { - return new DHBSSession(this, uid, dh_params); - } - - DHBS(Module *o) : Mechanism(o, "DH-BLOWFISH"), keysize(256 / 8) - { - if (!(dh_params = DH_new())) - throw ModuleException("DH_new() failed!"); - - if (!DH_generate_parameters_ex(dh_params, keysize * 8, 5, NULL)) - { - DH_free(dh_params); - throw ModuleException("Could not generate DH-params"); - } - } - - ~DHBS() - { - DH_free(dh_params); - } - - void ProcessMessage(SASL::Session *session, const SASL::Message &m) anope_override - { - DHBSSession *sess = anope_dynamic_static_cast<DHBSSession *>(session); - - if (!sess->dh) - { - sasl->SendMessage(sess, "D", "A"); - delete sess; - return; - } - - if (m.type == "S") - { - // Format: [ss]<p>[ss]<g>[ss]<pub_key> - // Where ss is a unsigned short with the size of the key - const BIGNUM* dhval[] = { sess->dh->p, sess->dh->g, sess->dh->pub_key }; - - // Find the size of our buffer - initialized at 6 because of string size data - size_t size = 6; - for (size_t i = 0; i < 3; i++) - size += BN_num_bytes(dhval[i]); - - // Fill in the DH data - std::vector<unsigned char> buffer(size); - for (size_t i = 0, pos = 0; i < 3; i++) - { - *reinterpret_cast<uint16_t*>(&buffer[pos]) = htons(BN_num_bytes(dhval[i])); - pos += 2; - BN_bn2bin(dhval[i], &buffer[pos]); - pos += BN_num_bytes(dhval[i]); - } - - Anope::string encoded; - Anope::B64Encode(Anope::string(buffer.begin(), buffer.end()), encoded); - sasl->SendMessage(sess, "C", encoded); - } - else if (m.type == "C") - { - // Make sure we have some data - actual size check is done later - if (m.data.length() < 10) - return Err(sess); - - // Format: [ss]<key><username><\0><encrypted> - - Anope::string decoded; - Anope::B64Decode(m.data, decoded); - - // As we rely on the client giving us a null terminator at the right place, - // let's add one extra in case the client tries to crash us - const size_t decodedlen = decoded.length(); - decoded.push_back('\0'); - - // Make sure we have enough data for at least the key, a one letter username, and a block of data - if (decodedlen < keysize + 2 + 2 + 8) - return Err(sess); - - const unsigned char* data = reinterpret_cast<const unsigned char*>(decoded.data()); - - // Control the size of the key - if (ntohs(*reinterpret_cast<const uint16_t*>(&data[0])) != keysize) - return Err(sess); - - // Convert pubkey from binary - size_t pos = 2; - BIGNUM* pubkey = BN_bin2bn(&data[pos], keysize, NULL); - if (!pubkey) - return Err(sess); - - // Find shared key - std::vector<unsigned char> secretkey(DH_size(sess->dh) + 1, 0); - if (DH_compute_key(&secretkey[0], pubkey, sess->dh) != static_cast<int>(keysize)) - return Err(sess, pubkey); - - // Set decryption key - BF_KEY BFKey; - BF_set_key(&BFKey, keysize, &secretkey[0]); - - pos += keysize; - const Anope::string username = reinterpret_cast<const char*>(&data[pos]); - // Check that the username is valid, and that we have at least one block of data - // 2 + 1 + 8 = uint16_t size for keylen, \0 for username, 8 for one block of data - if (username.empty() || username.length() + keysize + 2 + 1 + 8 > decodedlen || !IRCD->IsNickValid(username)) - return Err(sess, pubkey); - - pos += username.length() + 1; - size_t size = decodedlen - pos; - - // Blowfish data blocks are 64 bits wide - valid format? - if (size % 8) - return Err(sess, pubkey); - - std::vector<char> decrypted(size + 1, 0); - for (size_t i = 0; i < size; i += 8) - BF_ecb_encrypt(&data[pos + i], reinterpret_cast<unsigned char*>(&decrypted[i]), &BFKey, BF_DECRYPT); - - std::string password = &decrypted[0]; - if (password.empty() || password.find_first_of("\r\n") != Anope::string::npos) - return Err(sess, pubkey); - - SASL::IdentifyRequest* req = new SASL::IdentifyRequest(this->owner, m.source, username, password); - FOREACH_MOD(OnCheckAuthentication, (NULL, req)); - req->Dispatch(); - - BN_free(pubkey); - } - } -}; - - -class ModuleSASLDHBS : public Module -{ - DHBS dhbs; - - public: - ModuleSASLDHBS(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR | EXTRA), - dhbs(this) - { - } -}; - -MODULE_INIT(ModuleSASLDHBS) |