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
certutilwith the Visual C++ 2010 runtime, so running
certutilwithout that runtime installed produces an obvious error. However, in order to properly detect the built-in certificates (“CKBI”) that Firefox ships with,
certutilload the CKBI module that Firefox distributes (not the CKBI module that
certutilwas built with). This means that, when
certutilis 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,
certutillooks like it’s working – but the moment the Firefox CKBI module is loaded into
certutilexits 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. So
tlsrestrict_nss_tooldoesn’t actually know thet
certutilencountered an error; it just thinks it succeeded, and happened to produce no output. What happens if
certutilproduces no output when dumping the CKBI list? Well,
tlsrestrict_nss_tooljust figures that you’re using a Firefox build that doesn’t have any default trusted CA’s! This is bad enough when you first run
tlsrestrict_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 run
tlsrestrict_nss_tool, all of the name constraints that were previously added will get deleted, because
tlsrestrict_nss_toolfigures that those CA’s have vanished. How sad. The fix here is probably to make
tlsrestrict_nss_toolexplicitly 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 to
certutilvia 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 in
certutilreceiving a corrupted nickname to look up (and it correctly replies that no such nickname exists in the database). The fix here is to use
certutil’s “batch command” feature.
certutilallows you to put a sequence of commands into a
.txtfile, and you can pass that
.txtfile’s path to
certutilwith a command line flag;
certutilwill then run all of those commands. Since the
.txtfile isn’t parsed by Windows’s broken command line text decoder, Unicode inside the
.txtfile 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.