summaryrefslogtreecommitdiff
path: root/modules/sasl.cpp
diff options
context:
space:
mode:
authorSadie Powell <sadie@witchery.services>2025-02-05 13:32:12 +0000
committerSadie Powell <sadie@witchery.services>2025-02-05 13:45:15 +0000
commit8d3755af5b51049c229b3dcae474e743e7973ac4 (patch)
tree96a4ccffb2b73e44884586519d32fdfa4bb3b4c4 /modules/sasl.cpp
parent115c9eb5a0c5f604ef35cbb906f3603f26e5279c (diff)
Use fallback certs when doing SASL authentication.
Diffstat (limited to 'modules/sasl.cpp')
-rw-r--r--modules/sasl.cpp33
1 files changed, 23 insertions, 10 deletions
diff --git a/modules/sasl.cpp b/modules/sasl.cpp
index cb146d055..1c3fe717e 100644
--- a/modules/sasl.cpp
+++ b/modules/sasl.cpp
@@ -66,7 +66,7 @@ class External final
struct Session final
: SASL::Session
{
- Anope::string cert;
+ std::vector<Anope::string> certs;
Session(Mechanism *m, const Anope::string &u) : SASL::Session(m, u) { }
};
@@ -89,29 +89,42 @@ public:
if (m.type == "S")
{
- mysess->cert = m.data.size() > 1 ? "" : m.data[1];
+ mysess->certs.assign(m.data.begin() + 1, m.data.end());
sasl->SendMessage(sess, "C", "+");
}
else if (m.type == "C")
{
- if (!certs || mysess->cert.empty())
+ if (!certs || mysess->certs.empty())
return false;
Anope::string user = "A user";
if (!mysess->hostname.empty() && !mysess->ip.empty())
user = mysess->hostname + " (" + mysess->ip + ")";
- NickCore *nc = certs->FindAccountFromCert(mysess->cert);
- if (!nc || nc->HasExt("NS_SUSPENDED") || nc->HasExt("UNCONFIRMED"))
+
+ for (auto it = mysess->certs.begin(); it != mysess->certs.end(); ++it)
{
- Log(this->owner, "sasl", Config->GetClient("NickServ")) << user << " failed to identify using certificate " << mysess->cert << " using SASL EXTERNAL";
- return false;
+ auto *nc = certs->FindAccountFromCert(*it);
+ if (nc && !nc->HasExt("NS_SUSPENDED") && !nc->HasExt("UNCONFIRMED"))
+ {
+ // If we are using a fallback cert then upgrade it.
+ if (it != mysess->certs.begin())
+ {
+ auto *cl = nc->GetExt<NSCertList>("certificates");
+ if (cl)
+ cl->ReplaceCert(*it, mysess->certs[0]);
+ }
+
+ Log(this->owner, "sasl", Config->GetClient("NickServ")) << user << " identified to account " << nc->display << " using SASL EXTERNAL";
+ sasl->Succeed(sess, nc);
+ delete sess;
+ return true;
+ }
}
- Log(this->owner, "sasl", Config->GetClient("NickServ")) << user << " identified to account " << nc->display << " using SASL EXTERNAL";
- sasl->Succeed(sess, nc);
- delete sess;
+ Log(this->owner, "sasl", Config->GetClient("NickServ")) << user << " failed to identify using certificate " << mysess->certs.front() << " using SASL EXTERNAL";
+ return false;
}
return true;
}