1
0
mirror of https://github.com/anope/anope.git synced 2026-07-06 19:23:15 +02:00

Store a cert->account map and use it for SASL EXTERNAL and certfp auth

This commit is contained in:
Adam
2014-02-22 17:46:00 -05:00
parent 1db5c555d6
commit e836be489e
3 changed files with 57 additions and 22 deletions
+9
View File
@@ -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;
};
+41 -13
View File
@@ -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
+7 -9
View File
@@ -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;
}
}