Testing tlsrestrict_nss_tool on Windows
Now that we got NSS certutil
reproducibly cross-compiled for Windows, initial testing has begun on tlsrestrict_nss_tool
for Windows.
Besides the obvious and rather boring fail that tlsrestrict_nss_tool
was trying to execute cp
, which of course isn’t going to work on Windows (that particular code segment is a relic from quick prototyping that wasn’t ever intended to stay in the codebase), two more interesting issues were identified:
- rbm builds
certutil
with the Visual C++ 2010 runtime, so runningcertutil
without that runtime installed produces an obvious error. However, in order to properly detect the built-in certificates (“CKBI”) that Firefox ships with,tlsrestrict_nss_tool
makescertutil
load the CKBI module that Firefox distributes (not the CKBI module thatcertutil
was built with). This means that, whencertutil
is asked to load Firefox’s CKBI module, the Visual C++ runtime used by Firefox’s CKBI module also needs to be present. Which happens to be Visual C++ 2015. Without that,certutil
looks like it’s working – but the moment the Firefox CKBI module is loaded intocertutil
,certutil
exits with a missing DLL error. However, the situation is worsened by the fact that, as far as I can tell, a missing DLL error in Windows doesn’t impact the exit code. Sotlsrestrict_nss_tool
doesn’t actually know thetcertutil
encountered an error; it just thinks it succeeded, and happened to produce no output. What happens ifcertutil
produces no output when dumping the CKBI list? Well,tlsrestrict_nss_tool
just figures that you’re using a Firefox build that doesn’t have any default trusted CA’s! This is bad enough when you first runtlsrestrict_nss_tool
, since it will basically be a no-op. But even worse, if you did have the Visual C++ dependency from Firefox, but then Firefox upgraded it, then the next time you try to runtlsrestrict_nss_tool
, all of the name constraints that were previously added will get deleted, becausetlsrestrict_nss_tool
figures that those CA’s have vanished. How sad. The fix here is probably to maketlsrestrict_nss_tool
explicitly error if the CKBI module appears to have 0 certificates in it. Such a scenario pretty much always indicates that something has gone horribly wrong involving the CKBI module, and it’s generally best to treat it as an error. certutil
’s certificate dumping functions require selecting a certificate by its nickname. What’s a nickname? In practice, for the CKBI module it seems to be the CommonName of the certificate. The nickname is passed tocertutil
via a command line flag. What could possibly go wrong here? Certificate nicknames can be arbitrary text, including Unicode. What happens when you pass Unicode as a command line argument in Windows? Nothing good happens, that’s for sure. In my testing, Windows will corrupt all of the non-ASCII characters, which results incertutil
receiving a corrupted nickname to look up (and it correctly replies that no such nickname exists in the database). The fix here is to usecertutil
’s “batch command” feature.certutil
allows you to put a sequence of commands into a.txt
file, and you can pass that.txt
file’s path tocertutil
with a command line flag;certutil
will then run all of those commands. Since the.txt
file isn’t parsed by Windows’s broken command line text decoder, Unicode inside the.txt
file passes through unharmed.
Now, I haven’t actually fixed these bugs yet. But, progress is progress. Hopefully fixes will be coming very soon.
This work was funded by NLnet Foundation’s Internet Hardening Fund.