diff options
author | Adam <Adam@anope.org> | 2014-02-22 17:46:00 -0500 |
---|---|---|
committer | Adam <Adam@anope.org> | 2014-02-22 17:46:00 -0500 |
commit | e836be489e7997d5eac56d20ac779c3df2c5b91c (patch) | |
tree | 667d2fa25c14e955346d2f31fc644d98905356c2 | |
parent | 1db5c555d6ecf26ab15931c1a3db208fbb94a171 (diff) |
Store a cert->account map and use it for SASL EXTERNAL and certfp auth
-rw-r--r-- | include/modules/ns_cert.h | 9 | ||||
-rw-r--r-- | modules/commands/ns_cert.cpp | 54 | ||||
-rw-r--r-- | modules/m_sasl.cpp | 16 |
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; } } |