IRC Certificate Verification (Charybdis)
My pal Avi came to me with an interesting request the other day “please re-link the IRCDs”. Huh, that’s weird, I thought they were? Guess not, it seems they fell apart and won’t link. After some dicking around, I noted there were a couple of issues:
- we were enforcing SSL links - this makes sense, we don’t particularly care about security but confidentiality is a must-have.
- he’d upgraded his side to a new version, which requires fingerprinting and won’t do password auth if the SSL flag is on.
- My SSL certificate on the ircd had expired for some reason.
The first issue is not up for debate, but the second one absolutely was. Why enforce this? It makes zero sense, password auth over TLS is not great, but it’s infinitely better than no TLS at all. It’s probably a case of commenting out five lines to fix that:
if((yy_server->flags & SERVER_SSL) && EmptyString(yy_server->certfp))
{
conf_report_error("Ignoring connect block for %s -- no fingerprint provided for SSL connection.",
yy_server->name);
return 0;
}
Pretty sure if those lines were commented out, it’d revert to the old behaviour, but my days of maintaining a patchset to an ircd are over, I’d hope.
The fingerprint thing doubly didn’t make any sense, as once I fixed the expired certificate I noticed that the fingerprint changed. Yep, they’re verifying based off the certificate hash, not the pubkey. I threw my usual autistic temper tantrum on our IRC channel over it, and Avi happened to relay what I gather is a PG-13 summary of my grievance - namely that I think at the very least they should trust a certificate if it’s valid for the hostname specified in the configuration file, and trusted by the OS… and if they think that’s not enough (if it’s enough for me to validate my bank then surely it’s enough for IRC?), then let us use password auth as a backup. At the very least, fingerprint the pubkey rather than the certificate, because in the age of nearly-ubiquitous LetsEncrypt, where certificates last three months, it doesn’t make any sense to require manually changing the configuration file every time, and automating that requires either two-way trust between IRCds (not something I want), or neuters any security gained from it in the first place.
Long story short after a lengthy and, I gather, spirited discussion where someone else seemed to grok my concerns, I learned that Avi and I both hadn’t read the correct documenation because the latter is already supported. They call it SPKI and it’s apparently supported in Charybdis 3.5.4 and newer? Awesome, that should work!
Generating the hash is fairly simple (taken from the reference config, but saving here so I don’t have to dig it up again - also using BSD checksum commands, you would use sha512sum for Linux hosts):
openssl x509 -pubkey -noout -in /path/to/certificate.pem | openssl pkey -pubin -outform DER | sha512 | sed -r -e 's/^/SPKI:SHA2-512:/'
Take the resulting string, and place it in the fingerprint
field of the connect
block. Finally, in the general
block I had to change the certfp_method
:
certfp_method = spki_sha512;
After doing all of this, they linked together correctly and I can update my certificate without breaking the goddamn link. I still need to work out why the automatic renewal failed though…