I hate working on SSL stuff
I spent a bit of time over the last two weeks working on the SSL stuff for Mumble - I very much would like to be able to use Let’s Encrypt for Mumble servers (I suppose the plural isn’t really necessary, as I only have one left) and currently it involves restarting the server every time you want to update the certificate. How unpleasant.
The most obvious solution is to have Mumble re-read the certificate files on SIGHUP, but looking into that meant staring down a rabbit-hole of potential edge cases: working out what settings each virtual server inherited from the Metaserver, which ones to clobber, and what to do if the certificate was invalid for some reason. I’m not touching that task with a ten-foot-pole, I don’t get paid to do this.
Instead I took a look at the
initializeCertificate() function in
Cert.cpp and wondered if we could simply call that. The first hack was utterly terrible, I simply called
initializeCertificate() whenever the “certificate” setting was changed in Ice. This was ugly - if you set the certificate, then the key, Mumble would blow away everything and generate itself a new certificate, but if you set everything in the correct order and held your mouth just right, it did work.
I ended up in a weird situation where setting an invalid key kicked everyone off the server, and I couldn’t work out why - there was nothing obvious in the code to make that happen… any change to the certificate should not affect users with already established sessions. In the process, I managed to get the attention of @mkrautz, who took the whole thing and ran with it. Not only did he discover a weird bug in the way we use OpenSSL/QSslSocket, which caused the mass-disconnect (and might have actually been a DoS, had we looked hard enough, now that I think of it) but he figured out a much more robust way of updating the certificates on the server via Ice.
So I end up getting what I want, and I didn’t have to do much of the work!
While goofing around with the SSL certificates though, I noticed that you can ask the server to disclose the private key to you, and if the certificate and private key are set via the Metaserver (that is, specified in the
murmur.ini), it’ll disclose the private key in plain text. I thought the latter was much more serious, but it turns out that you can ask the server for the passphrase for the encrypted private key, so it’s a bit moot. I ended up plugging that hole too - there’s a tiny chance it’ll break someone’s Ice script (I doubt it, unless they’re really “doing it wrong” anyway). If we stop the server from disclosing the private key and the ssl passphrase, it really doesn’t matter if we don’t store the private key in encrypted format in the Metaserver anyway, since it needs to be in memory anyway and if someone has access to read the process’s memory it’s game-over to begin with.
However Mumble ships with Ice bound to localhost, and no “read” secret - so anyone on the local machine could pick up the SSL private key. That’s probably not a hair-on-fire security emergency, since most people run with self-signed certificates and the workaround is simply to set a secret on Ice for read as well as write, but as more people start using real certificates it could become a concern - an SSL private key is very much a “cat out of the bag” situation, as they generally cost money to revoke if stolen.
Anyway, my changes got landed in Mumble itself, hopefully I haven’t broken anything.