mirror of
https://github.com/anope/anope.git
synced 2026-07-07 23:23:13 +02:00
Merge pull request #48 from ShutterQuick/2.0+nnghsasl
Add SASL mechanisms DH-AES and DH-BLOWFISH
This commit is contained in:
@@ -428,11 +428,27 @@ module { name = "help" }
|
||||
*
|
||||
* Some IRCds allow "SASL" authentication to let users identify to Services
|
||||
* during the IRCd user registration process. If this module is loaded, Services will allow
|
||||
* authenticating users through this mechanism. Currently supported mechanisms are:
|
||||
* authenticating users through this mechanism. Supported mechanisms are:
|
||||
* PLAIN, EXTERNAL.
|
||||
*/
|
||||
#module { name = "m_sasl" }
|
||||
|
||||
/*
|
||||
* m_sasl_dh-aes [EXTRA]
|
||||
*
|
||||
* Add the DH-AES mechanism to SASL.
|
||||
* Requires m_sasl to be loaded.
|
||||
*/
|
||||
#module { name = "m_sasl_dh-aes" }
|
||||
|
||||
/*
|
||||
* m_sasl_dh-aes [EXTRA]
|
||||
*
|
||||
* Add the DH-BLOWFISH mechanism to SASL.
|
||||
* Requires m_sasl to be loaded.
|
||||
*/
|
||||
#module { name = "m_sasl_dh-blowfish" }
|
||||
|
||||
/*
|
||||
* m_sql_authentication [EXTRA]
|
||||
*
|
||||
|
||||
@@ -115,6 +115,7 @@ namespace Anope
|
||||
* The following functions return the various types of strings.
|
||||
*/
|
||||
inline const char *c_str() const { return this->_string.c_str(); }
|
||||
inline const char *data() const { return this->_string.data(); }
|
||||
inline std::string &str() { return this->_string; }
|
||||
inline const std::string &str() const { return this->_string; }
|
||||
inline ci::string ci_str() const { return ci::string(this->_string.c_str()); }
|
||||
|
||||
+76
-24
@@ -18,27 +18,7 @@ namespace SASL
|
||||
};
|
||||
|
||||
class Mechanism;
|
||||
|
||||
struct Session
|
||||
{
|
||||
time_t created;
|
||||
Anope::string uid;
|
||||
Reference<Mechanism> mech;
|
||||
|
||||
Session(Mechanism *m, const Anope::string &u) : created(Anope::CurTime), uid(u), mech(m) { }
|
||||
virtual ~Session() { }
|
||||
};
|
||||
|
||||
/* PLAIN, EXTERNAL, etc */
|
||||
class Mechanism : public Service
|
||||
{
|
||||
public:
|
||||
Mechanism(Module *o, const Anope::string &sname) : Service(o, "SASL::Mechanism", sname) { }
|
||||
|
||||
virtual Session* CreateSession(const Anope::string &uid) { return new Session(this, uid); }
|
||||
|
||||
virtual void ProcessMessage(Session *session, const Message &) = 0;
|
||||
};
|
||||
struct Session;
|
||||
|
||||
class Service : public ::Service
|
||||
{
|
||||
@@ -56,8 +36,80 @@ namespace SASL
|
||||
virtual void Succeed(Session *, NickCore *) = 0;
|
||||
virtual void Fail(Session *) = 0;
|
||||
virtual void SendMechs(Session *) = 0;
|
||||
virtual void DeleteSessions(Mechanism *, bool = false) = 0;
|
||||
virtual void RemoveSession(Session *) = 0;
|
||||
};
|
||||
|
||||
static ServiceReference<SASL::Service> sasl("SASL::Service", "sasl");
|
||||
|
||||
struct Session
|
||||
{
|
||||
time_t created;
|
||||
Anope::string uid;
|
||||
Reference<Mechanism> mech;
|
||||
|
||||
Session(Mechanism *m, const Anope::string &u) : created(Anope::CurTime), uid(u), mech(m) { }
|
||||
virtual ~Session()
|
||||
{
|
||||
if (sasl)
|
||||
sasl->RemoveSession(this);
|
||||
}
|
||||
};
|
||||
|
||||
/* PLAIN, EXTERNAL, etc */
|
||||
class Mechanism : public ::Service
|
||||
{
|
||||
public:
|
||||
Mechanism(Module *o, const Anope::string &sname) : Service(o, "SASL::Mechanism", sname) { }
|
||||
|
||||
virtual Session* CreateSession(const Anope::string &uid) { return new Session(this, uid); }
|
||||
|
||||
virtual void ProcessMessage(Session *session, const Message &) = 0;
|
||||
|
||||
virtual ~Mechanism()
|
||||
{
|
||||
if (sasl)
|
||||
sasl->DeleteSessions(this, true);
|
||||
}
|
||||
};
|
||||
|
||||
class IdentifyRequest : public ::IdentifyRequest
|
||||
{
|
||||
Anope::string uid;
|
||||
|
||||
public:
|
||||
IdentifyRequest(Module *m, const Anope::string &id, const Anope::string &acc, const Anope::string &pass) : ::IdentifyRequest(m, acc, pass), uid(id) { }
|
||||
|
||||
void OnSuccess() anope_override
|
||||
{
|
||||
if (!sasl)
|
||||
return;
|
||||
|
||||
NickAlias *na = NickAlias::Find(GetAccount());
|
||||
if (!na)
|
||||
return OnFail();
|
||||
|
||||
Session *s = sasl->GetSession(uid);
|
||||
if (s)
|
||||
{
|
||||
sasl->Succeed(s, na->nc);
|
||||
delete s;
|
||||
}
|
||||
}
|
||||
|
||||
void OnFail() anope_override
|
||||
{
|
||||
if (!sasl)
|
||||
return;
|
||||
|
||||
Session *s = sasl->GetSession(uid);
|
||||
if (s)
|
||||
{
|
||||
sasl->Fail(s);
|
||||
delete s;
|
||||
}
|
||||
|
||||
Log(Config->GetClient("NickServ")) << "A user failed to identify for account " << this->GetAccount() << " using SASL";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static ServiceReference<SASL::Service> sasl("SASL::Service", "sasl");
|
||||
|
||||
|
||||
@@ -0,0 +1,183 @@
|
||||
/* RequiredLibraries: ssl,crypto */
|
||||
|
||||
#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);
|
||||
return delete sess;
|
||||
}
|
||||
|
||||
public:
|
||||
struct Session : SASL::Session
|
||||
{
|
||||
DH* dh;
|
||||
Session(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;
|
||||
}
|
||||
}
|
||||
|
||||
~Session()
|
||||
{
|
||||
if (dh)
|
||||
DH_free(dh);
|
||||
}
|
||||
};
|
||||
|
||||
DH* dh_params;
|
||||
const size_t keysize;
|
||||
SASL::Session* CreateSession(const Anope::string &uid) anope_override
|
||||
{
|
||||
return new Session(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
|
||||
{
|
||||
Session *sess = anope_dynamic_static_cast<Session *>(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())
|
||||
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)
|
||||
@@ -0,0 +1,193 @@
|
||||
/* RequiredLibraries: ssl,crypto */
|
||||
|
||||
#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);
|
||||
return delete sess;
|
||||
}
|
||||
|
||||
public:
|
||||
struct Session : SASL::Session
|
||||
{
|
||||
DH* dh;
|
||||
Session(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;
|
||||
}
|
||||
}
|
||||
|
||||
~Session()
|
||||
{
|
||||
if (dh)
|
||||
DH_free(dh);
|
||||
}
|
||||
};
|
||||
|
||||
DH* dh_params;
|
||||
const size_t keysize;
|
||||
SASL::Session* CreateSession(const Anope::string &uid) anope_override
|
||||
{
|
||||
return new Session(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
|
||||
{
|
||||
Session *sess = anope_dynamic_static_cast<Session *>(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)
|
||||
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())
|
||||
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)
|
||||
+43
-53
@@ -10,46 +10,14 @@
|
||||
#include "modules/sasl.h"
|
||||
#include "modules/ns_cert.h"
|
||||
|
||||
class Plain : public SASL::Mechanism
|
||||
using namespace SASL;
|
||||
|
||||
class Plain : public Mechanism
|
||||
{
|
||||
class IdentifyRequest : public ::IdentifyRequest
|
||||
{
|
||||
Anope::string uid;
|
||||
|
||||
public:
|
||||
IdentifyRequest(Module *m, const Anope::string &id, const Anope::string &acc, const Anope::string &pass) : ::IdentifyRequest(m, acc, pass), uid(id) { }
|
||||
|
||||
void OnSuccess() anope_override
|
||||
{
|
||||
if (!sasl)
|
||||
return;
|
||||
|
||||
NickAlias *na = NickAlias::Find(GetAccount());
|
||||
if (!na)
|
||||
return OnFail();
|
||||
|
||||
SASL::Session *s = sasl->GetSession(uid);
|
||||
if (s)
|
||||
sasl->Succeed(s, na->nc);
|
||||
}
|
||||
|
||||
void OnFail() anope_override
|
||||
{
|
||||
if (!sasl)
|
||||
return;
|
||||
|
||||
SASL::Session *s = sasl->GetSession(uid);
|
||||
if (s)
|
||||
sasl->Fail(s);
|
||||
|
||||
Log(Config->GetClient("NickServ")) << "A user failed to identify for account " << this->GetAccount() << " using SASL";
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
Plain(Module *o) : SASL::Mechanism(o, "PLAIN") { }
|
||||
Plain(Module *o) : Mechanism(o, "PLAIN") { }
|
||||
|
||||
void ProcessMessage(SASL::Session *sess, const SASL::Message &m) anope_override
|
||||
void ProcessMessage(Session *sess, const SASL::Message &m) anope_override
|
||||
{
|
||||
if (m.type == "S")
|
||||
{
|
||||
@@ -75,14 +43,14 @@ class Plain : public SASL::Mechanism
|
||||
if (acc.empty() || pass.empty())
|
||||
return;
|
||||
|
||||
IdentifyRequest *req = new IdentifyRequest(this->owner, m.source, acc, pass);
|
||||
SASL::IdentifyRequest *req = new SASL::IdentifyRequest(this->owner, m.source, acc, pass);
|
||||
FOREACH_MOD(OnCheckAuthentication, (NULL, req));
|
||||
req->Dispatch();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class External : public SASL::Mechanism
|
||||
class External : public Mechanism
|
||||
{
|
||||
struct Session : SASL::Session
|
||||
{
|
||||
@@ -92,13 +60,13 @@ class External : public SASL::Mechanism
|
||||
};
|
||||
|
||||
public:
|
||||
External(Module *o) : SASL::Mechanism(o, "EXTERNAL")
|
||||
External(Module *o) : Mechanism(o, "EXTERNAL")
|
||||
{
|
||||
if (!IRCD || !IRCD->CanCertFP)
|
||||
throw ModuleException("No CertFP");
|
||||
}
|
||||
|
||||
SASL::Session* CreateSession(const Anope::string &uid) anope_override
|
||||
Session* CreateSession(const Anope::string &uid) anope_override
|
||||
{
|
||||
return new Session(this, uid);
|
||||
}
|
||||
@@ -122,6 +90,7 @@ class External : public SASL::Mechanism
|
||||
if (!na)
|
||||
{
|
||||
sasl->Fail(sess);
|
||||
delete sess;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -129,10 +98,12 @@ class External : public SASL::Mechanism
|
||||
if (cl == NULL || !cl->FindCert(mysess->cert))
|
||||
{
|
||||
sasl->Fail(sess);
|
||||
delete sess;
|
||||
return;
|
||||
}
|
||||
|
||||
sasl->Succeed(sess, na->nc);
|
||||
delete sess;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -146,7 +117,7 @@ class SASLService : public SASL::Service, public Timer
|
||||
|
||||
~SASLService()
|
||||
{
|
||||
for (std::map<Anope::string, SASL::Session *>::iterator it = sessions.begin(); it != sessions.end();)
|
||||
for (std::map<Anope::string, Session *>::iterator it = sessions.begin(); it != sessions.end(); it++)
|
||||
delete it->second;
|
||||
}
|
||||
|
||||
@@ -163,14 +134,14 @@ class SASLService : public SASL::Service, public Timer
|
||||
}
|
||||
}
|
||||
|
||||
SASL::Session* &session = sessions[m.source];
|
||||
Session* &session = sessions[m.source];
|
||||
|
||||
if (m.type == "S")
|
||||
{
|
||||
ServiceReference<SASL::Mechanism> mech("SASL::Mechanism", m.data);
|
||||
ServiceReference<Mechanism> mech("SASL::Mechanism", m.data);
|
||||
if (!mech)
|
||||
{
|
||||
SASL::Session tmp(NULL, m.source);
|
||||
Session tmp(NULL, m.source);
|
||||
|
||||
sasl->SendMechs(&tmp);
|
||||
sasl->Fail(&tmp);
|
||||
@@ -200,15 +171,34 @@ class SASLService : public SASL::Service, public Timer
|
||||
return agent;
|
||||
}
|
||||
|
||||
SASL::Session* GetSession(const Anope::string &uid) anope_override
|
||||
Session* GetSession(const Anope::string &uid) anope_override
|
||||
{
|
||||
std::map<Anope::string, SASL::Session *>::iterator it = sessions.find(uid);
|
||||
std::map<Anope::string, Session *>::iterator it = sessions.find(uid);
|
||||
if (it != sessions.end())
|
||||
return it->second;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void SendMessage(SASL::Session *session, const Anope::string &mtype, const Anope::string &data) anope_override
|
||||
void RemoveSession(Session *sess) anope_override
|
||||
{
|
||||
sessions.erase(sess->uid);
|
||||
}
|
||||
|
||||
void DeleteSessions(Mechanism *mech, bool da) anope_override
|
||||
{
|
||||
for (std::map<Anope::string, Session *>::iterator it = sessions.begin(); it != sessions.end();)
|
||||
{
|
||||
std::map<Anope::string, Session *>::iterator del = it++;
|
||||
if (*del->second->mech == mech)
|
||||
{
|
||||
if (da)
|
||||
this->SendMessage(del->second, "D", "A");
|
||||
delete del->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SendMessage(Session *session, const Anope::string &mtype, const Anope::string &data) anope_override
|
||||
{
|
||||
SASL::Message msg;
|
||||
msg.source = this->GetAgent();
|
||||
@@ -219,18 +209,18 @@ class SASLService : public SASL::Service, public Timer
|
||||
IRCD->SendSASLMessage(msg);
|
||||
}
|
||||
|
||||
void Succeed(SASL::Session *session, NickCore *nc) anope_override
|
||||
void Succeed(Session *session, NickCore *nc) anope_override
|
||||
{
|
||||
IRCD->SendSVSLogin(session->uid, nc->display);
|
||||
this->SendMessage(session, "D", "S");
|
||||
}
|
||||
|
||||
void Fail(SASL::Session *session) anope_override
|
||||
void Fail(Session *session) anope_override
|
||||
{
|
||||
this->SendMessage(session, "D", "F");
|
||||
}
|
||||
|
||||
void SendMechs(SASL::Session *session) anope_override
|
||||
void SendMechs(Session *session) anope_override
|
||||
{
|
||||
std::vector<Anope::string> mechs = Service::GetServiceKeys("SASL::Mechanism");
|
||||
Anope::string buf;
|
||||
@@ -242,10 +232,10 @@ class SASLService : public SASL::Service, public Timer
|
||||
|
||||
void Tick(time_t) anope_override
|
||||
{
|
||||
for (std::map<Anope::string, SASL::Session *>::iterator it = sessions.begin(); it != sessions.end();)
|
||||
for (std::map<Anope::string, Session *>::iterator it = sessions.begin(); it != sessions.end();)
|
||||
{
|
||||
Anope::string key = it->first;
|
||||
SASL::Session *s = it->second;
|
||||
Session *s = it->second;
|
||||
++it;
|
||||
|
||||
if (!s || !s->mech || s->created + 60 < Anope::CurTime)
|
||||
|
||||
@@ -188,7 +188,7 @@ struct IRCDMessageEncap : IRCDMessage
|
||||
*
|
||||
* Charybdis only accepts messages from SASL agents; these must have umode +S
|
||||
*/
|
||||
if (params[1] == "SASL" && sasl && params.size() >= 6)
|
||||
if (params[1] == "SASL" && SASL::sasl && params.size() >= 6)
|
||||
{
|
||||
SASL::Message m;
|
||||
m.source = params[2];
|
||||
@@ -197,7 +197,7 @@ struct IRCDMessageEncap : IRCDMessage
|
||||
m.data = params[5];
|
||||
m.ext = params.size() > 6 ? params[6] : "";
|
||||
|
||||
sasl->ProcessMessage(m);
|
||||
SASL::sasl->ProcessMessage(m);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -873,7 +873,7 @@ struct IRCDMessageEncap : IRCDMessage
|
||||
if (Anope::Match(Me->GetSID(), params[0]) == false)
|
||||
return;
|
||||
|
||||
if (sasl && params[1] == "SASL" && params.size() >= 6)
|
||||
if (SASL::sasl && params[1] == "SASL" && params.size() >= 6)
|
||||
{
|
||||
SASL::Message m;
|
||||
m.source = params[2];
|
||||
@@ -882,7 +882,7 @@ struct IRCDMessageEncap : IRCDMessage
|
||||
m.data = params[5];
|
||||
m.ext = params.size() > 6 ? params[6] : "";
|
||||
|
||||
sasl->ProcessMessage(m);
|
||||
SASL::sasl->ProcessMessage(m);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1283,7 +1283,7 @@ struct IRCDMessageUID : IRCDMessage
|
||||
modes += " " + params[i];
|
||||
|
||||
NickAlias *na = NULL;
|
||||
if (sasl)
|
||||
if (SASL::sasl)
|
||||
for (std::list<SASLUser>::iterator it = saslusers.begin(); it != saslusers.end();)
|
||||
{
|
||||
SASLUser &u = *it;
|
||||
|
||||
@@ -889,7 +889,7 @@ struct IRCDMessageSASL : IRCDMessage
|
||||
void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override
|
||||
{
|
||||
size_t p = params[1].find('!');
|
||||
if (!sasl || p == Anope::string::npos)
|
||||
if (!SASL::sasl || p == Anope::string::npos)
|
||||
return;
|
||||
|
||||
SASL::Message m;
|
||||
@@ -899,7 +899,7 @@ struct IRCDMessageSASL : IRCDMessage
|
||||
m.data = params[3];
|
||||
m.ext = params.size() > 4 ? params[4] : "";
|
||||
|
||||
sasl->ProcessMessage(m);
|
||||
SASL::sasl->ProcessMessage(m);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+1
-1
@@ -159,7 +159,7 @@ void Anope::B64Decode(const Anope::string &src, Anope::string &target)
|
||||
state = 0;
|
||||
}
|
||||
}
|
||||
if (!target[target.length() - 1])
|
||||
if (!target.empty() && !target[target.length() - 1])
|
||||
target.erase(target.length() - 1);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user