diff options
author | Adam <adam@sigterm.info> | 2014-02-14 19:15:43 -0500 |
---|---|---|
committer | Adam <adam@sigterm.info> | 2014-02-14 19:15:43 -0500 |
commit | 50d7bf710ec0501b7309892646a31da065aaae5a (patch) | |
tree | 85e664dfdeb38c1cae4bb03bddc76a183ab2d34e | |
parent | ca85df2d7475d42579c29d822f424d2c9713774b (diff) | |
parent | d44bcef31b7a6cbb607249bf39273c0e32b1f60a (diff) |
Merge pull request #48 from ShutterQuick/2.0+nnghsasl
Add SASL mechanisms DH-AES and DH-BLOWFISH
-rw-r--r-- | data/modules.example.conf | 18 | ||||
-rw-r--r-- | include/anope.h | 1 | ||||
-rw-r--r-- | include/modules/sasl.h | 80 | ||||
-rw-r--r-- | modules/extra/m_sasl_dh-aes.cpp | 183 | ||||
-rw-r--r-- | modules/extra/m_sasl_dh-blowfish.cpp | 193 | ||||
-rw-r--r-- | modules/m_sasl.cpp | 96 | ||||
-rw-r--r-- | modules/protocol/charybdis.cpp | 4 | ||||
-rw-r--r-- | modules/protocol/inspircd12.cpp | 6 | ||||
-rw-r--r-- | modules/protocol/unreal.cpp | 4 | ||||
-rw-r--r-- | src/base64.cpp | 2 |
10 files changed, 511 insertions, 76 deletions
diff --git a/data/modules.example.conf b/data/modules.example.conf index 319bc1e27..df2077b4d 100644 --- a/data/modules.example.conf +++ b/data/modules.example.conf @@ -428,12 +428,28 @@ 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] * * This module allows authenticating users against an external SQL database using a custom diff --git a/include/anope.h b/include/anope.h index 28bc50512..638661440 100644 --- a/include/anope.h +++ b/include/anope.h @@ -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()); } diff --git a/include/modules/sasl.h b/include/modules/sasl.h index 836c26d19..a7c440110 100644 --- a/include/modules/sasl.h +++ b/include/modules/sasl.h @@ -18,6 +18,29 @@ namespace SASL }; class Mechanism; + struct Session; + + class Service : public ::Service + { + public: + Service(Module *o) : ::Service(o, "SASL::Service", "sasl") { } + + virtual void ProcessMessage(const Message &) = 0; + + virtual Anope::string GetAgent() = 0; + + virtual Session* GetSession(const Anope::string &uid) = 0; + + virtual void SendMessage(SASL::Session *session, const Anope::string &type, const Anope::string &data) = 0; + + 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 { @@ -26,11 +49,15 @@ namespace SASL Reference<Mechanism> mech; Session(Mechanism *m, const Anope::string &u) : created(Anope::CurTime), uid(u), mech(m) { } - virtual ~Session() { } + virtual ~Session() + { + if (sasl) + sasl->RemoveSession(this); + } }; /* PLAIN, EXTERNAL, etc */ - class Mechanism : public Service + class Mechanism : public ::Service { public: Mechanism(Module *o, const Anope::string &sname) : Service(o, "SASL::Mechanism", sname) { } @@ -38,26 +65,51 @@ namespace SASL 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 Service : public ::Service + class IdentifyRequest : public ::IdentifyRequest { + Anope::string uid; + public: - Service(Module *o) : ::Service(o, "SASL::Service", "sasl") { } + IdentifyRequest(Module *m, const Anope::string &id, const Anope::string &acc, const Anope::string &pass) : ::IdentifyRequest(m, acc, pass), uid(id) { } - virtual void ProcessMessage(const Message &) = 0; + void OnSuccess() anope_override + { + if (!sasl) + return; - virtual Anope::string GetAgent() = 0; + NickAlias *na = NickAlias::Find(GetAccount()); + if (!na) + return OnFail(); - virtual Session* GetSession(const Anope::string &uid) = 0; + Session *s = sasl->GetSession(uid); + if (s) + { + sasl->Succeed(s, na->nc); + delete s; + } + } - virtual void SendMessage(SASL::Session *session, const Anope::string &type, const Anope::string &data) = 0; + void OnFail() anope_override + { + if (!sasl) + return; - virtual void Succeed(Session *, NickCore *) = 0; - virtual void Fail(Session *) = 0; - virtual void SendMechs(Session *) = 0; + 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"); - diff --git a/modules/extra/m_sasl_dh-aes.cpp b/modules/extra/m_sasl_dh-aes.cpp new file mode 100644 index 000000000..c61430a62 --- /dev/null +++ b/modules/extra/m_sasl_dh-aes.cpp @@ -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) diff --git a/modules/extra/m_sasl_dh-blowfish.cpp b/modules/extra/m_sasl_dh-blowfish.cpp new file mode 100644 index 000000000..a31d4727b --- /dev/null +++ b/modules/extra/m_sasl_dh-blowfish.cpp @@ -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) diff --git a/modules/m_sasl.cpp b/modules/m_sasl.cpp index bdc0ef1a2..c99f052ae 100644 --- a/modules/m_sasl.cpp +++ b/modules/m_sasl.cpp @@ -10,46 +10,14 @@ #include "modules/sasl.h" #include "modules/ns_cert.h" -class Plain : public SASL::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"; - } - }; +using namespace SASL; +class Plain : public Mechanism +{ 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) diff --git a/modules/protocol/charybdis.cpp b/modules/protocol/charybdis.cpp index e9ea89673..a0c10be83 100644 --- a/modules/protocol/charybdis.cpp +++ b/modules/protocol/charybdis.cpp @@ -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); } } }; diff --git a/modules/protocol/inspircd12.cpp b/modules/protocol/inspircd12.cpp index e64079dca..eded20306 100644 --- a/modules/protocol/inspircd12.cpp +++ b/modules/protocol/inspircd12.cpp @@ -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; diff --git a/modules/protocol/unreal.cpp b/modules/protocol/unreal.cpp index e0f051aa6..f0d01ce9d 100644 --- a/modules/protocol/unreal.cpp +++ b/modules/protocol/unreal.cpp @@ -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); } }; diff --git a/src/base64.cpp b/src/base64.cpp index 420290a34..d4d9ff43e 100644 --- a/src/base64.cpp +++ b/src/base64.cpp @@ -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); } |