summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2014-02-22 17:46:00 -0500
committerAdam <Adam@anope.org>2014-02-22 17:46:00 -0500
commite836be489e7997d5eac56d20ac779c3df2c5b91c (patch)
tree667d2fa25c14e955346d2f31fc644d98905356c2
parent1db5c555d6ecf26ab15931c1a3db208fbb94a171 (diff)
Store a cert->account map and use it for SASL EXTERNAL and certfp auth
-rw-r--r--include/modules/ns_cert.h9
-rw-r--r--modules/commands/ns_cert.cpp54
-rw-r--r--modules/m_sasl.cpp16
3 files changed, 57 insertions, 22 deletions
diff --git a/include/modules/ns_cert.h b/include/modules/ns_cert.h
index ca3f333fd..e02b9bd6e 100644
--- a/include/modules/ns_cert.h
+++ b/include/modules/ns_cert.h
@@ -60,3 +60,12 @@ struct NSCertList
virtual void Check() = 0;
};
+
+class CertService : public Service
+{
+ public:
+ CertService(Module *c) : Service(c, "CertService", "certs") { }
+
+ virtual NickCore* FindAccountFromCert(const Anope::string &cert) = 0;
+};
+
diff --git a/modules/commands/ns_cert.cpp b/modules/commands/ns_cert.cpp
index 427f4c151..7bd498e74 100644
--- a/modules/commands/ns_cert.cpp
+++ b/modules/commands/ns_cert.cpp
@@ -12,6 +12,21 @@
#include "module.h"
#include "modules/ns_cert.h"
+static Anope::hash_map<NickCore *> certmap;
+
+struct CertServiceImpl : CertService
+{
+ CertServiceImpl(Module *o) : CertService(o) { }
+
+ NickCore* FindAccountFromCert(const Anope::string &cert) anope_override
+ {
+ Anope::hash_map<NickCore *>::iterator it = certmap.find(cert);
+ if (it != certmap.end())
+ return it->second;
+ return NULL;
+ }
+};
+
struct NSCertListImpl : NSCertList
{
Serialize::Reference<NickCore> nc;
@@ -20,6 +35,11 @@ struct NSCertListImpl : NSCertList
public:
NSCertListImpl(Extensible *obj) : nc(anope_dynamic_static_cast<NickCore *>(obj)) { }
+ ~NSCertListImpl()
+ {
+ ClearCert();
+ }
+
/** Add an entry to the nick's certificate list
*
* @param entry The fingerprint to add to the cert list
@@ -29,6 +49,7 @@ struct NSCertListImpl : NSCertList
void AddCert(const Anope::string &entry) anope_override
{
this->certs.push_back(entry);
+ certmap[entry] = nc;
FOREACH_MOD(OnNickAddCert, (this->nc, entry));
}
@@ -75,6 +96,7 @@ struct NSCertListImpl : NSCertList
if (it != this->certs.end())
{
FOREACH_MOD(OnNickEraseCert, (this->nc, entry));
+ certmap.erase(entry);
this->certs.erase(it);
}
}
@@ -86,6 +108,8 @@ struct NSCertListImpl : NSCertList
void ClearCert() anope_override
{
FOREACH_MOD(OnNickClearCert, (this->nc));
+ for (unsigned i = 0; i < certs.size(); ++i)
+ certmap.erase(certs[i]);
this->certs.clear();
}
@@ -124,9 +148,12 @@ struct NSCertListImpl : NSCertList
Anope::string buf;
data["cert"] >> buf;
spacesepstream sep(buf);
- c->certs.clear();
+ c->ClearCert();
while (sep.GetToken(buf))
+ {
c->certs.push_back(buf);
+ certmap[buf] = n;
+ }
}
};
};
@@ -308,10 +335,11 @@ class NSCert : public Module
{
CommandNSCert commandnscert;
NSCertListImpl::ExtensibleItem certs;
+ CertServiceImpl cs;
public:
NSCert(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
- commandnscert(this), certs(this, "certificates")
+ commandnscert(this), certs(this, "certificates"), cs(this)
{
if (!IRCD || !IRCD->CanCertFP)
throw ModuleException("Your IRCd does not support ssl client certificates");
@@ -319,22 +347,22 @@ class NSCert : public Module
void OnFingerprint(User *u) anope_override
{
- NickAlias *na = NickAlias::Find(u->nick);
BotInfo *NickServ = Config->GetClient("NickServ");
- if (!NickServ || !na)
- return;
- if (u->IsIdentified() && u->Account() == na->nc)
- return;
- if (na->nc->HasExt("NS_SUSPENDED"))
+ if (!NickServ || u->IsIdentified())
return;
- NSCertList *cl = certs.Get(na->nc);
- if (!cl || !cl->FindCert(u->fingerprint))
+ NickCore *nc = cs.FindAccountFromCert(u->fingerprint);
+ if (!nc || nc->HasExt("NS_SUSPENDED"))
return;
- u->Identify(na);
- u->SendMessage(NickServ, _("SSL certificate fingerprint accepted, you are now identified."));
- Log(NickServ) << u->GetMask() << " automatically identified for account " << na->nc->display << " via SSL certificate fingerprint";
+ NickAlias *na = NickAlias::Find(u->nick);
+ if (na && na->nc == nc)
+ u->Identify(na);
+ else
+ u->Login(nc);
+
+ u->SendMessage(NickServ, _("SSL certificate fingerprint accepted, you are now identified to \2%s\2."), nc->display.c_str());
+ Log(NickServ) << u->GetMask() << " automatically identified for account " << nc->display << " via SSL certificate fingerprint";
}
EventReturn OnNickValidate(User *u, NickAlias *na) anope_override
diff --git a/modules/m_sasl.cpp b/modules/m_sasl.cpp
index c99f052ae..18de8930b 100644
--- a/modules/m_sasl.cpp
+++ b/modules/m_sasl.cpp
@@ -52,6 +52,8 @@ class Plain : public Mechanism
class External : public Mechanism
{
+ ServiceReference<CertService> certs;
+
struct Session : SASL::Session
{
Anope::string cert;
@@ -60,7 +62,7 @@ class External : public Mechanism
};
public:
- External(Module *o) : Mechanism(o, "EXTERNAL")
+ External(Module *o) : Mechanism(o, "EXTERNAL"), certs("CertService", "certs")
{
if (!IRCD || !IRCD->CanCertFP)
throw ModuleException("No CertFP");
@@ -83,26 +85,22 @@ class External : public Mechanism
}
else if (m.type == "C")
{
- Anope::string account;
- Anope::B64Decode(m.data, account);
-
- NickAlias *na = NickAlias::Find(account);
- if (!na)
+ if (!certs)
{
sasl->Fail(sess);
delete sess;
return;
}
- NSCertList *cl = na->nc->GetExt<NSCertList>("certificates");
- if (cl == NULL || !cl->FindCert(mysess->cert))
+ NickCore *nc = certs->FindAccountFromCert(mysess->cert);
+ if (!nc)
{
sasl->Fail(sess);
delete sess;
return;
}
- sasl->Succeed(sess, na->nc);
+ sasl->Succeed(sess, nc);
delete sess;
}
}