summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Powell <petpow@saberuk.com>2016-04-13 20:26:50 +0100
committerPeter Powell <petpow@saberuk.com>2016-04-13 20:26:50 +0100
commitf4f6787c9ccdbcb675e0c81129abce469f694d94 (patch)
tree43391b25121c696e1ae5f507432fe71a9501ec2f
parent79e7c3f98a57b7cffc46d9a7dc250a0e6e25fc98 (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.conf18
-rw-r--r--modules/extra/m_sasl_dh-aes.cpp193
-rw-r--r--modules/extra/m_sasl_dh-blowfish.cpp203
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)