summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/example.conf7
-rw-r--r--data/modules.example.conf10
-rw-r--r--include/defs.h1
-rw-r--r--include/modules/sasl.h63
-rw-r--r--include/protocol.h3
-rw-r--r--modules/m_sasl.cpp284
-rw-r--r--modules/protocol/charybdis.cpp104
-rw-r--r--modules/protocol/inspircd12.cpp124
-rw-r--r--modules/protocol/inspircd20.cpp2
-rw-r--r--modules/protocol/unreal.cpp100
10 files changed, 448 insertions, 250 deletions
diff --git a/data/example.conf b/data/example.conf
index 4762ad084..fbb7e310e 100644
--- a/data/example.conf
+++ b/data/example.conf
@@ -276,13 +276,6 @@ module
* If the protocol module you have loaded does not support this, this setting will have no effect.
*/
use_server_side_topiclock = yes
-
- /*
- * Some IRCds allow "SASL" authentication to let users identify to Services
- * during the IRCd user registration process. If set, Services will allow
- * authenticating users through this mechanism.
- */
- sasl = yes
}
/*
diff --git a/data/modules.example.conf b/data/modules.example.conf
index 8e41aa734..57430e2a7 100644
--- a/data/modules.example.conf
+++ b/data/modules.example.conf
@@ -424,6 +424,16 @@ module { name = "help" }
}
/*
+ * m_sasl
+ *
+ * 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:
+ * PLAIN, EXTERNAL.
+ */
+module { name = "m_sasl" }
+
+/*
* m_sql_authentication [EXTRA]
*
* This module allows authenticating users against an external SQL database using a custom
diff --git a/include/defs.h b/include/defs.h
index 1d61c6c92..3d8ebf4ff 100644
--- a/include/defs.h
+++ b/include/defs.h
@@ -52,4 +52,5 @@ struct Exception;
struct MemoInfo;
struct ModeLock;
struct Oper;
+namespace SASL { struct Message; }
diff --git a/include/modules/sasl.h b/include/modules/sasl.h
new file mode 100644
index 000000000..836c26d19
--- /dev/null
+++ b/include/modules/sasl.h
@@ -0,0 +1,63 @@
+/*
+ *
+ * (C) 2014 Anope Team
+ * Contact us at team@anope.org
+ *
+ * Please read COPYING and README for further details.
+ */
+
+namespace SASL
+{
+ struct Message
+ {
+ Anope::string source;
+ Anope::string target;
+ Anope::string type;
+ Anope::string data;
+ Anope::string ext;
+ };
+
+ 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;
+ };
+
+ 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;
+ };
+}
+
+static ServiceReference<SASL::Service> sasl("SASL::Service", "sasl");
+
diff --git a/include/protocol.h b/include/protocol.h
index 9eee494ea..0f8482b4e 100644
--- a/include/protocol.h
+++ b/include/protocol.h
@@ -217,6 +217,9 @@ class CoreExport IRCDProto : public Service
*/
virtual void SendOper(User *u);
+ virtual void SendSASLMessage(const SASL::Message &) { }
+ virtual void SendSVSLogin(const Anope::string &uid, const Anope::string &acc) { }
+
virtual bool IsNickValid(const Anope::string &);
virtual bool IsChannelValid(const Anope::string &);
virtual bool IsIdentValid(const Anope::string &);
diff --git a/modules/m_sasl.cpp b/modules/m_sasl.cpp
new file mode 100644
index 000000000..bdc0ef1a2
--- /dev/null
+++ b/modules/m_sasl.cpp
@@ -0,0 +1,284 @@
+/*
+ *
+ * (C) 2014 Anope Team
+ * Contact us at team@anope.org
+ *
+ * Please read COPYING and README for further details.
+ */
+
+#include "module.h"
+#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";
+ }
+ };
+
+ public:
+ Plain(Module *o) : SASL::Mechanism(o, "PLAIN") { }
+
+ void ProcessMessage(SASL::Session *sess, const SASL::Message &m) anope_override
+ {
+ if (m.type == "S")
+ {
+ sasl->SendMessage(sess, "C", "+");
+ }
+ else if (m.type == "C")
+ {
+ Anope::string decoded;
+ Anope::B64Decode(m.data, decoded);
+
+ size_t p = decoded.find('\0');
+ if (p == Anope::string::npos)
+ return;
+ decoded = decoded.substr(p + 1);
+
+ p = decoded.find('\0');
+ if (p == Anope::string::npos)
+ return;
+
+ Anope::string acc = decoded.substr(0, p),
+ pass = decoded.substr(p + 1);
+
+ if (acc.empty() || pass.empty())
+ return;
+
+ IdentifyRequest *req = new IdentifyRequest(this->owner, m.source, acc, pass);
+ FOREACH_MOD(OnCheckAuthentication, (NULL, req));
+ req->Dispatch();
+ }
+ }
+};
+
+class External : public SASL::Mechanism
+{
+ struct Session : SASL::Session
+ {
+ Anope::string cert;
+
+ Session(Mechanism *m, const Anope::string &u) : SASL::Session(m, u) { }
+ };
+
+ public:
+ External(Module *o) : SASL::Mechanism(o, "EXTERNAL")
+ {
+ if (!IRCD || !IRCD->CanCertFP)
+ throw ModuleException("No CertFP");
+ }
+
+ SASL::Session* CreateSession(const Anope::string &uid) anope_override
+ {
+ return new Session(this, uid);
+ }
+
+ void ProcessMessage(SASL::Session *sess, const SASL::Message &m) anope_override
+ {
+ Session *mysess = anope_dynamic_static_cast<Session *>(sess);
+
+ if (m.type == "S")
+ {
+ mysess->cert = m.ext;
+
+ sasl->SendMessage(sess, "C", "+");
+ }
+ else if (m.type == "C")
+ {
+ Anope::string account;
+ Anope::B64Decode(m.data, account);
+
+ NickAlias *na = NickAlias::Find(account);
+ if (!na)
+ {
+ sasl->Fail(sess);
+ return;
+ }
+
+ NSCertList *cl = na->nc->GetExt<NSCertList>("certificates");
+ if (cl == NULL || !cl->FindCert(mysess->cert))
+ {
+ sasl->Fail(sess);
+ return;
+ }
+
+ sasl->Succeed(sess, na->nc);
+ }
+ }
+};
+
+class SASLService : public SASL::Service, public Timer
+{
+ std::map<Anope::string, SASL::Session *> sessions;
+
+ public:
+ SASLService(Module *o) : SASL::Service(o), Timer(o, 60, Anope::CurTime, true) { }
+
+ ~SASLService()
+ {
+ for (std::map<Anope::string, SASL::Session *>::iterator it = sessions.begin(); it != sessions.end();)
+ delete it->second;
+ }
+
+ void ProcessMessage(const SASL::Message &m) anope_override
+ {
+ if (m.target != "*")
+ {
+ Server *s = Server::Find(m.target);
+ if (s != Me)
+ {
+ User *u = User::Find(m.target);
+ if (!u || u->server != Me)
+ return;
+ }
+ }
+
+ SASL::Session* &session = sessions[m.source];
+
+ if (m.type == "S")
+ {
+ ServiceReference<SASL::Mechanism> mech("SASL::Mechanism", m.data);
+ if (!mech)
+ {
+ SASL::Session tmp(NULL, m.source);
+
+ sasl->SendMechs(&tmp);
+ sasl->Fail(&tmp);
+ return;
+ }
+
+ if (!session)
+ session = mech->CreateSession(m.source);
+ }
+ else if (m.type == "D")
+ {
+ delete session;
+ sessions.erase(m.source);
+ return;
+ }
+
+ if (session && session->mech)
+ session->mech->ProcessMessage(session, m);
+ }
+
+ Anope::string GetAgent() anope_override
+ {
+ Anope::string agent = Config->GetModule(Service::owner)->Get<Anope::string>("agent", "NickServ");
+ BotInfo *bi = Config->GetClient(agent);
+ if (bi)
+ agent = bi->GetUID();
+ return agent;
+ }
+
+ SASL::Session* GetSession(const Anope::string &uid) anope_override
+ {
+ std::map<Anope::string, SASL::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
+ {
+ SASL::Message msg;
+ msg.source = this->GetAgent();
+ msg.target = session->uid;
+ msg.type = mtype;
+ msg.data = data;
+
+ IRCD->SendSASLMessage(msg);
+ }
+
+ void Succeed(SASL::Session *session, NickCore *nc) anope_override
+ {
+ IRCD->SendSVSLogin(session->uid, nc->display);
+ this->SendMessage(session, "D", "S");
+ }
+
+ void Fail(SASL::Session *session) anope_override
+ {
+ this->SendMessage(session, "D", "F");
+ }
+
+ void SendMechs(SASL::Session *session) anope_override
+ {
+ std::vector<Anope::string> mechs = Service::GetServiceKeys("SASL::Mechanism");
+ Anope::string buf;
+ for (unsigned j = 0; j < mechs.size(); ++j)
+ buf += "," + mechs[j];
+
+ this->SendMessage(session, "M", buf.empty() ? "" : buf.substr(1));
+ }
+
+ void Tick(time_t) anope_override
+ {
+ for (std::map<Anope::string, SASL::Session *>::iterator it = sessions.begin(); it != sessions.end();)
+ {
+ Anope::string key = it->first;
+ SASL::Session *s = it->second;
+ ++it;
+
+ if (!s || !s->mech || s->created + 60 < Anope::CurTime)
+ {
+ delete s;
+ sessions.erase(key);
+ }
+ }
+ }
+};
+
+class ModuleSASL : public Module
+{
+ SASLService sasl;
+
+ Plain plain;
+ External *external;
+
+ public:
+ ModuleSASL(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
+ sasl(this), plain(this), external(NULL)
+ {
+ try
+ {
+ external = new External(this);
+ }
+ catch (ModuleException &) { }
+ }
+
+ ~ModuleSASL()
+ {
+ delete external;
+ }
+};
+
+MODULE_INIT(ModuleSASL)
diff --git a/modules/protocol/charybdis.cpp b/modules/protocol/charybdis.cpp
index b1d2e6614..e9ea89673 100644
--- a/modules/protocol/charybdis.cpp
+++ b/modules/protocol/charybdis.cpp
@@ -11,8 +11,8 @@
#include "module.h"
#include "modules/cs_mode.h"
+#include "modules/sasl.h"
-static bool sasl = true;
static Anope::string UplinkSID;
static ServiceReference<IRCDProto> ratbox("IRCDProto", "ratbox");
@@ -140,6 +140,18 @@ class CharybdisProto : public IRCDProto
{
this->SendVhost(u, "", u->host);
}
+
+ void SendSASLMessage(const SASL::Message &message) anope_override
+ {
+ Server *s = Server::Find(message.target.substr(0, 3));
+ UplinkSocket::Message(Me) << "ENCAP " << (s ? s->GetName() : message.target.substr(0, 3)) << " SASL " << message.source << " " << message.target << " " << message.type << " " << message.data << (message.ext.empty() ? "" : (" " + message.ext));
+ }
+
+ void SendSVSLogin(const Anope::string &uid, const Anope::string &acc) anope_override
+ {
+ Server *s = Server::Find(uid.substr(0, 3));
+ UplinkSocket::Message(Me) << "ENCAP " << (s ? s->GetName() : uid.substr(0, 3)) << " SVSLOGIN " << uid << " * * * " << acc;
+ }
};
@@ -176,87 +188,16 @@ 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 && params.size() >= 6)
{
- class CharybdisSASLIdentifyRequest : public IdentifyRequest
- {
- Anope::string uid;
- MessageSource msource;
-
- public:
- CharybdisSASLIdentifyRequest(Module *m, MessageSource &source_, const Anope::string &id, const Anope::string &acc, const Anope::string &pass) : IdentifyRequest(m, acc, pass), uid(id), msource(source_) { }
-
- void OnSuccess() anope_override
- {
- BotInfo *NickServ = Config->GetClient("NickServ");
- if (!NickServ)
- return;
-
- Anope::string accountname = GetAccount();
- NickAlias *na = NickAlias::Find(accountname);
- if (na)
- accountname = na->nc->display;
-
- /* SVSLOGIN
- * parameters: target, new nick, new username, new visible hostname, new login name
- * Sent after successful SASL authentication.
- * The target is a UID, typically an unregistered one.
- * Any of the "new" parameters can be '*' to leave the corresponding field
- * unchanged. The new login name can be '0' to log the user out.
- * If the UID is registered on the network, a SIGNON with the changes will be
- * broadcast, otherwise the changes will be stored, to be used when registration
- * completes.
- */
- UplinkSocket::Message(Me) << "ENCAP " << msource.GetName() << " SVSLOGIN " << this->uid << " * * * " << accountname;
- UplinkSocket::Message(Me) << "ENCAP " << msource.GetName() << " SASL " << NickServ->GetUID() << " " << this->uid << " D S";
- }
-
- void OnFail() anope_override
- {
- BotInfo *NickServ = Config->GetClient("NickServ");
- if (!NickServ)
- return;
-
- UplinkSocket::Message(Me) << "ENCAP " << msource.GetName() << " SASL " << NickServ->GetUID() << " " << this->uid << " " << " D F";
-
- Log(NickServ) << "A user failed to identify for account " << this->GetAccount() << " using SASL";
- }
- };
- if (params[4] == "S")
- {
- BotInfo *NickServ = Config->GetClient("NickServ");
- if (!NickServ)
- return;
-
- if (params[5] == "PLAIN")
- UplinkSocket::Message(Me) << "ENCAP " << source.GetName() << " SASL " << NickServ->GetUID() << " " << params[2] << " C +";
- else
- UplinkSocket::Message(Me) << "ENCAP " << source.GetName() << " SASL " << NickServ->GetUID() << " " << params[2] << " D F";
- }
- else if (params[4] == "C")
- {
- Anope::string decoded;
- Anope::B64Decode(params[5], decoded);
-
- size_t p = decoded.find('\0');
- if (p == Anope::string::npos)
- return;
- decoded = decoded.substr(p + 1);
-
- p = decoded.find('\0');
- if (p == Anope::string::npos)
- return;
-
- Anope::string acc = decoded.substr(0, p),
- pass = decoded.substr(p + 1);
-
- if (acc.empty() || pass.empty())
- return;
-
- IdentifyRequest *req = new CharybdisSASLIdentifyRequest(this->owner, source, params[2], acc, pass);
- FOREACH_MOD(OnCheckAuthentication, (NULL, req));
- req->Dispatch();
- }
+ SASL::Message m;
+ m.source = params[2];
+ m.target = params[3];
+ m.type = params[4];
+ m.data = params[5];
+ m.ext = params.size() > 6 ? params[6] : "";
+
+ sasl->ProcessMessage(m);
}
}
};
@@ -422,7 +363,6 @@ class ProtoCharybdis : public Module
void OnReload(Configuration::Conf *conf) anope_override
{
use_server_side_mlock = conf->GetModule(this)->Get<bool>("use_server_side_mlock");
- sasl = conf->GetModule(this)->Get<bool>("sasl");
}
void OnChannelSync(Channel *c) anope_override
diff --git a/modules/protocol/inspircd12.cpp b/modules/protocol/inspircd12.cpp
index 328049c64..e64079dca 100644
--- a/modules/protocol/inspircd12.cpp
+++ b/modules/protocol/inspircd12.cpp
@@ -10,6 +10,7 @@
*/
#include "module.h"
+#include "modules/sasl.h"
struct SASLUser
{
@@ -18,7 +19,6 @@ struct SASLUser
time_t created;
};
-static bool sasl = true;
static std::list<SASLUser> saslusers;
static Anope::string rsquit_server, rsquit_id;
@@ -398,6 +398,33 @@ class InspIRCd12Proto : public IRCDProto
{
}
+ void SendSASLMessage(const SASL::Message &message) anope_override
+ {
+ UplinkSocket::Message(Me) << "ENCAP " << message.target.substr(0, 3) << " SASL " << message.source << " " << message.target << " " << message.type << " " << message.data << (message.ext.empty() ? "" : (" " + message.ext));
+ }
+
+ void SendSVSLogin(const Anope::string &uid, const Anope::string &acc) anope_override
+ {
+ UplinkSocket::Message(Me) << "METADATA " << uid << " accountname :" << acc;
+
+ SASLUser su;
+ su.uid = uid;
+ su.acc = acc;
+ su.created = Anope::CurTime;
+
+ for (std::list<SASLUser>::iterator it = saslusers.begin(); it != saslusers.end();)
+ {
+ SASLUser &u = *it;
+
+ if (u.created + 30 < Anope::CurTime || u.uid == uid)
+ it = saslusers.erase(it);
+ else
+ ++it;
+ }
+
+ saslusers.push_back(su);
+ }
+
bool IsExtbanValid(const Anope::string &mask) anope_override
{
return mask.length() >= 3 && mask[1] == ':';
@@ -846,88 +873,16 @@ struct IRCDMessageEncap : IRCDMessage
if (Anope::Match(Me->GetSID(), params[0]) == false)
return;
- if (sasl && params[1] == "SASL" && params.size() == 6)
+ if (sasl && params[1] == "SASL" && params.size() >= 6)
{
- class InspIRCDSASLIdentifyRequest : public IdentifyRequest
- {
- Anope::string uid;
-
- public:
- InspIRCDSASLIdentifyRequest(Module *m, const Anope::string &id, const Anope::string &acc, const Anope::string &pass) : IdentifyRequest(m, acc, pass), uid(id) { }
-
- void OnSuccess() anope_override
- {
- Anope::string accountname = GetAccount();
- NickAlias *na = NickAlias::Find(accountname);
- if (na)
- accountname = na->nc->display;
-
- UplinkSocket::Message(Me) << "METADATA " << this->uid << " accountname :" << accountname;
- UplinkSocket::Message(Me) << "ENCAP " << this->uid.substr(0, 3) << " SASL " << Me->GetSID() << " " << this->uid << " D S";
-
- SASLUser su;
- su.uid = this->uid;
- su.acc = this->GetAccount();
- su.created = Anope::CurTime;
-
- for (std::list<SASLUser>::iterator it = saslusers.begin(); it != saslusers.end();)
- {
- SASLUser &u = *it;
-
- if (u.created + 30 < Anope::CurTime || u.uid == this->uid)
- it = saslusers.erase(it);
- else
- ++it;
- }
-
- saslusers.push_back(su);
- }
-
- void OnFail() anope_override
- {
- UplinkSocket::Message(Me) << "ENCAP " << this->uid.substr(0, 3) << " SASL " << Me->GetSID() << " " << this->uid << " " << " D F";
-
- Log(Config->GetClient("NickServ")) << "A user failed to identify for account " << this->GetAccount() << " using SASL";
- }
- };
-
- /*
- Received: :869 ENCAP * SASL 869AAAAAH * S PLAIN
- Sent: :00B ENCAP 869 SASL 00B 869AAAAAH C +
- Received: :869 ENCAP * SASL 869AAAAAH 00B C QWRhbQBBZGFtAG1vbw==
- base64(account\0account\0pass)
- */
- if (params[4] == "S")
- {
- if (params[5] == "PLAIN")
- UplinkSocket::Message(Me) << "ENCAP " << params[2].substr(0, 3) << " SASL " << Me->GetSID() << " " << params[2] << " C +";
- else
- UplinkSocket::Message(Me) << "ENCAP " << params[2].substr(0, 3) << " SASL " << Me->GetSID() << " " << params[2] << " D F";
- }
- else if (params[4] == "C")
- {
- Anope::string decoded;
- Anope::B64Decode(params[5], decoded);
-
- size_t p = decoded.find('\0');
- if (p == Anope::string::npos)
- return;
- decoded = decoded.substr(p + 1);
-
- p = decoded.find('\0');
- if (p == Anope::string::npos)
- return;
-
- Anope::string acc = decoded.substr(0, p),
- pass = decoded.substr(p + 1);
-
- if (acc.empty() || pass.empty())
- return;
-
- IdentifyRequest *req = new InspIRCDSASLIdentifyRequest(this->owner, params[2], acc, pass);
- FOREACH_MOD(OnCheckAuthentication, (NULL, req));
- req->Dispatch();
- }
+ SASL::Message m;
+ m.source = params[2];
+ m.target = params[3];
+ m.type = params[4];
+ m.data = params[5];
+ m.ext = params.size() > 6 ? params[6] : "";
+
+ sasl->ProcessMessage(m);
}
}
};
@@ -1407,11 +1362,6 @@ class ProtoInspIRCd12 : public Module
Servers::Capab.insert("NOQUIT");
}
- void OnReload(Configuration::Conf *conf) anope_override
- {
- sasl = conf->GetModule(this)->Get<bool>("sasl") || conf->GetModule("inspircd20")->Get<bool>("sasl");
- }
-
void OnUserNickChange(User *u, const Anope::string &) anope_override
{
/* InspIRCd 1.2 doesn't set -r on nick change, remove -r here. Note that if we have to set +r later
diff --git a/modules/protocol/inspircd20.cpp b/modules/protocol/inspircd20.cpp
index 6ee000f68..4e88d01a8 100644
--- a/modules/protocol/inspircd20.cpp
+++ b/modules/protocol/inspircd20.cpp
@@ -71,6 +71,8 @@ class InspIRCd20Proto : public IRCDProto
void SendLogin(User *u, NickAlias *na) anope_override { insp12->SendLogin(u, na); }
void SendLogout(User *u) anope_override { insp12->SendLogout(u); }
void SendChannel(Channel *c) anope_override { insp12->SendChannel(c); }
+ void SendSASLMessage(const SASL::Message &message) anope_override { insp12->SendSASLMessage(message); }
+ void SendSVSLogin(const Anope::string &uid, const Anope::string &acc) anope_override { insp12->SendSVSLogin(uid, acc); }
bool IsExtbanValid(const Anope::string &mask) anope_override { return insp12->IsExtbanValid(mask); }
bool IsIdentValid(const Anope::string &ident) anope_override { return insp12->IsIdentValid(ident); }
};
diff --git a/modules/protocol/unreal.cpp b/modules/protocol/unreal.cpp
index 00f7cc586..e0f051aa6 100644
--- a/modules/protocol/unreal.cpp
+++ b/modules/protocol/unreal.cpp
@@ -11,8 +11,7 @@
#include "module.h"
#include "modules/cs_mode.h"
-
-static bool sasl = true;
+#include "modules/sasl.h"
class UnrealIRCdProto : public IRCDProto
{
@@ -377,6 +376,23 @@ class UnrealIRCdProto : public IRCDProto
}
}
+ void SendSASLMessage(const SASL::Message &message) anope_override
+ {
+ size_t p = message.target.find('!');
+ if (p == Anope::string::npos)
+ return;
+
+ UplinkSocket::Message(BotInfo::Find(message.source)) << "SASL " << message.target.substr(0, p) << " " << message.target << " " << message.type << " " << message.data << (message.ext.empty() ? "" : " " + message.ext);
+ }
+
+ void SendSVSLogin(const Anope::string &uid, const Anope::string &acc) anope_override
+ {
+ size_t p = uid.find('!');
+ if (p == Anope::string::npos)
+ return;
+ UplinkSocket::Message(Me) << "SVSLOGIN " << uid.substr(0, p) << " " << uid << " " << acc;
+ }
+
bool IsIdentValid(const Anope::string &ident) anope_override
{
if (ident.empty() || ident.length() > Config->GetBlock("networkinfo")->Get<unsigned>("userlen"))
@@ -868,85 +884,22 @@ struct IRCDMessagePong : IRCDMessage
struct IRCDMessageSASL : IRCDMessage
{
- class UnrealSASLIdentifyRequest : public IdentifyRequest
- {
- Anope::string uid;
-
- public:
- UnrealSASLIdentifyRequest(Module *m, const Anope::string &id, const Anope::string &acc, const Anope::string &pass) : IdentifyRequest(m, acc, pass), uid(id) { }
-
- void OnSuccess() anope_override
- {
- size_t p = this->uid.find('!');
- if (p == Anope::string::npos)
- return;
-
- Anope::string accountname = GetAccount();
- NickAlias *na = NickAlias::Find(accountname);
- if (na)
- accountname = na->nc->display;
-
- UplinkSocket::Message(Me) << "SVSLOGIN " << this->uid.substr(0, p) << " " << this->uid << " " << accountname;
- UplinkSocket::Message() << "SASL " << this->uid.substr(0, p) << " " << this->uid << " D S";
- }
+ IRCDMessageSASL(Module *creator) : IRCDMessage(creator, "SASL", 4) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
- void OnFail() anope_override
- {
- size_t p = this->uid.find('!');
- if (p == Anope::string::npos)
- return;
-
- UplinkSocket::Message() << "SASL " << this->uid.substr(0, p) << " " << this->uid << " D F";
-
- Log(Config->GetClient("NickServ")) << "A user failed to identify for account " << this->GetAccount() << " using SASL";
- }
- };
-
- IRCDMessageSASL(Module *creator) : IRCDMessage(creator, "SASL", 4) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
-
- /* Received: :irc.foonet.com SASL services.localhost.net irc.foonet.com!1.57290 S PLAIN
- * uid
- *
- * Received: :irc.foonet.com SASL services.localhost.net irc.foonet.com!3.56270 C QWRhbQBBZGFtAHF3ZXJ0eQ==
- * uid base64(account\0account\0pass)
- */
void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
{
size_t p = params[1].find('!');
if (!sasl || p == Anope::string::npos)
return;
- if (params[2] == "S")
- {
- if (params[3] == "PLAIN")
- UplinkSocket::Message() << "SASL " << params[1].substr(0, p) << " " << params[1] << " C +";
- else
- UplinkSocket::Message() << "SASL " << params[1].substr(0, p) << " " << params[1] << " D F";
- }
- else if (params[2] == "C")
- {
- Anope::string decoded;
- Anope::B64Decode(params[3], decoded);
-
- p = decoded.find('\0');
- if (p == Anope::string::npos)
- return;
- decoded = decoded.substr(p + 1);
-
- p = decoded.find('\0');
- if (p == Anope::string::npos)
- return;
+ SASL::Message m;
+ m.source = params[1];
+ m.target = params[0];
+ m.type = params[2];
+ m.data = params[3];
+ m.ext = params.size() > 4 ? params[4] : "";
- Anope::string acc = decoded.substr(0, p),
- pass = decoded.substr(p + 1);
-
- if (acc.empty() || pass.empty())
- return;
-
- IdentifyRequest *req = new UnrealSASLIdentifyRequest(this->owner, params[1], acc, pass);
- FOREACH_MOD(OnCheckAuthentication, (NULL, req));
- req->Dispatch();
- }
+ sasl->ProcessMessage(m);
}
};
@@ -1241,7 +1194,6 @@ class ProtoUnreal : public Module
void OnReload(Configuration::Conf *conf) anope_override
{
use_server_side_mlock = conf->GetModule(this)->Get<bool>("use_server_side_mlock");
- sasl = conf->GetModule(this)->Get<bool>("sasl");
}
void OnUserNickChange(User *u, const Anope::string &) anope_override