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
certutilwith the Visual C++ 2010 runtime, so runningcertutilwithout that runtime installed produces an obvious error. However, in order to properly detect the built-in certificates (“CKBI”) that Firefox ships with,tlsrestrict_nss_toolmakescertutilload the CKBI module that Firefox distributes (not the CKBI module thatcertutilwas built with). This means that, whencertutilis 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 intocertutil,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. Sotlsrestrict_nss_tooldoesn’t actually know thetcertutilencountered an error; it just thinks it succeeded, and happened to produce no output. What happens ifcertutilproduces 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 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_toolfigures that those CA’s have vanished. How sad. The fix here is probably to maketlsrestrict_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 tocertutilvia 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 incertutilreceiving 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.certutilallows you to put a sequence of commands into a.txtfile, and you can pass that.txtfile’s path tocertutilwith 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.