As a web generalist, I have my hands on just about everything involved in building and managing websites… including server administration. So while I’m not a dedicated sysadmin, I deal with the Linux command line for my clients often enough that I have been aware for a few weeks of the impending “Let’s Encrypt Apocalypse.”
The what?
I don’t really know a lot about how SSL encryption works, but I do know (now) that every device connected to the Internet has root certificates, which are part of the process of verifying the identity of other devices when establishing an encrypted connection. Root certificates are pretty important, and they don’t expire often.
But they do expire.
One particular root certificate used by Let’s Encrypt — the open source Certificate Authority that has saved me countless hours of agony — was set to expire today, September 30, 2021.
Let’s Encrypt has long since added a newer root certificate that doesn’t expire until 2035. But remember how I said root certificates are installed on every device connected to the Internet? Yeah, and when two devices are trying to establish an encrypted connection to each other, they need to agree on using the same root certificate to build that connection. Which means that root certificate needs to be present on both devices.
Like Let’s Encrypt, most modern OSes have also long since added the newer root certificates, so they have more than one way to talk to a server that’s using Let’s Encrypt. But some don’t. In particular, here are some that don’t:
- Windows < XP SP3
- macOS < 10.12.1
- iOS < 10
- Android < 7.1.1
I’ve spent a lot of today fielding emails from my clients who have been fielding calls from their site users who are running some of these OSes, and who now can’t access their websites.
Unfortunately… uh… there’s not really a fix. Oh sure, you can manually install new root certificates. Which is something that ordinary people totally deal with on a daily basis. Right? Yeah, not so much. There’s one other semi-reasonable option: Use Firefox instead of your default browser. That’s because Firefox includes its own root certificates, instead of relying on the ones installed by the OS.
But how does all of this matter to ICS Calendar?
Well, that lack of updated root certificates is not just a client issue. Some servers don’t have the updated root certificates either, especially if they’re running an old version of Linux or an unpatched version of OpenSSL. They should be updated, just like users’ devices should be updated. But it’s not entirely reasonable for someone in my position to expect that to happen. What to do?
My first email this morning was from an ICS Calendar user in Germany whose calendars had stopped loading. Initially I didn’t make the connection… I didn’t think about what day it was. But eventually I realized this might be the problem, and on further investigation I confirmed it: their source calendar server was using a Let’s Encrypt cert that was built on the expired X3 root certificate.
You know those annoying warning pages your browser will throw at you if you try to connect to a website with an expired SSL certificate? Well, by default, PHP technologies that connect to other servers to retrieve files, like cURL and fopen, also throw a similar fuss if they’re not able to verify the SSL certificate on the other side.
But just like how you can tell your web browser to “proceed anyway” and show you the site you were trying to access, PHP allows you to tell it not to worry about these errors. It’s called peer verification, and you can skip it if you want.
Ideally it’s better not to skip it, but this isn’t an ideal world, is it? As a developer, I generally need to be cautious about disregarding this kind of security step, but evaluating the nature of ICS Calendar — the type of data it’s retrieving, and what it does with what it’s received — I determined that it is reasonably safe to skip peer verification in this plugin. So that’s what I did.
Specifically, in the function that it uses to connect to remote servers to retrieve calendar data, which uses cURL and then falls back to fopen, I made a couple of changes:
First, I turned off peer verification in cURL with this:
curl_setopt($conn, CURLOPT_SSL_VERIFYPEER, false);
Then, in the fopen fallback code, I added a “context” telling it likewise to skip peer verification:
$context = stream_context_create(array('ssl' => array('verify_peer' => false)));
$url_contents = file_get_contents($url, false, $context);
That was it! The user in Germany reports back that their calendar is now up and running once again. I may not be able to get my old iPod Touch to load any websites, but at least ICS Calendar is no longer a contributing factor in the Let’s Encrypt Apocalypse!
The fix is now available in version 8.5.1.
—Scott