Join GitHub today
GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.Sign up
windows/certificates: Improve table's coverage of Personal certificates #5640
This is a follow up PR to #5631.
The winapis for certificate store enumeration generally do not show any certificates for other users' Personal stores, even when there are certificates there. Furthermore, whether the table shows information about other users' stores depends on whether the user has a registry hive mounted, which can be affected by events e.g. whether the user has logged in since boot. Personal certificates are actually stored on disk, rather than in the registry, which makes it possible to reliably read them (from an Admin process), regardless of whether they belong to a different user, and regardless of the state of the system's login history. This PR takes advantage of this to make the certificates table more complete wrt Personal certificates; Personal certificates are now guaranteed to show for all users, regardless of login history.
I measured performance of the table with the
Disabled (average, ms): 1582
It really depends on the number of local users on the system, and the number of personal certs on disk each of them have, but I believe those should typically both be fairly low, so I don't think this PR should affect performance dramatically.
Here's an example screenshot of it running:
Here's 1 full line of output when run in json mode (happens to have been run on a different machine):
Here's a gist of full output after a fresh boot where only
Here's full output after
For additional testing, I added a certificate into the Local System account's directory for Personal certificates. This exists inside
This code is hard to unit test because the testing system needs to have certificates and user accounts set up in a certain way. Writing a mock layer is also difficult due to the nature of the system APIs and the way they use (nested) callbacks. In general, for testing I placed a number of certificates explicitly in the Personal stores of several users on the system and ensured the queries could always find at least all Personal certificates I had installed, regardless of the user login history.
They aren't returned by the cert enumeration APIs, but if we directly look into their %APPDATA%, we can find them. The files there are a custom file format, which we can parse to extract the actual encoded certificate. We can then forward that back to the winapi to extract info out of it. We can also proactively look for them on disk, regardless of the enumeration, which will guarantee that we will always be able to show Personal certs regardless of things like, e.g. login history. For example, if a user has never logged in on a system since boot, they may not appear in the registry, and thus the enumeration, so their Personal certs will not appear, even though they are available.
Lgtm! I had a couple of nits/thoughts on the work. I think one last bit that has been discussed by the small council is we'd like to see unit tests for diffs coming in? Any chance you could add some unit tests for the table? Looks like we've already got some built out, would it be easy to extend the testing to add some checks for your code and increase the coverage?
Similar to the user_groups table, we filter out some of the accounts we know will not have directories on disk for certificates
Previously, we assumed a certain path structure for where to find a user's Personal certificates. Now we reuse some functionality from the users table which checks the registry to retrieve the home directory.
For system accounts (e.g. Local System) the home dir paths we get back from getUserHomeDir may contain environment variables. This expands them so we can now retrieve certificates within certificate directories for system accounts.