[Mono.Security] Check NewLocalMachinePath too for deciding if store is machine store...
authorAlexander Köplinger <alex.koeplinger@outlook.com>
Thu, 9 Feb 2017 17:30:53 +0000 (18:30 +0100)
committerGitHub <noreply@github.com>
Thu, 9 Feb 2017 17:30:53 +0000 (18:30 +0100)
The code in X509Store only checked the legacy X509StoreManager.LocalMachinePath
when deciding whether CspProviderFlags.UseMachineKeyStore should be
set when dealing with private keys.

However, with BTLS we now also have X509StoreManager.NewLocalMachinePath.

This caused an issue/regression in the recent 4.8 builds that
started importing into the BTLS cert store when using cert-sync:
https://github.com/mono/mono/commit/968c60a0f32c7a4c92568c3feda7503f99b98c94

Because cert-sync is ran at package installation time as root
on Linux we would erroneously not pass UseMachineKeyStore (because
the paths between legacy and BTLS store are different), which in turn
causes KeyPairPersistence to look into the user directory, e.g.
~/.config/.mono/keypairs. Since on a clean machine that directory
hierarchy doesn't exist, it goes on and creates it -> we now have
the ~/.config directory owned by root which means a normal user
application can't write to it anymore (like NuGet) and crashes.

The fix is to check for the BTLS store path as well so KeyPairPersistence
uses the machine path and ~/.config is not created on package installation.

See e.g. https://github.com/travis-ci/travis-ci/issues/7271

mcs/class/Mono.Security/Mono.Security.X509/X509Store.cs

index 536782fd0c2ea85a8795e9a0ee81726aa8ee9848..1821075635ddbc343dfd2fe42944ddc46b11cd20 100644 (file)
@@ -163,7 +163,7 @@ namespace Mono.Security.X509 {
                        cspParams.KeyContainerName = CryptoConvert.ToHex (certificate.Hash);
 
                        // Right now this seems to be the best way to know if we should use LM store.. ;)
-                       if (_storePath.StartsWith (X509StoreManager.LocalMachinePath))
+                       if (_storePath.StartsWith (X509StoreManager.LocalMachinePath) || _storePath.StartsWith(X509StoreManager.NewLocalMachinePath))
                                cspParams.Flags = CspProviderFlags.UseMachineKeyStore;
 
                        ImportPrivateKey (certificate, cspParams);
@@ -338,7 +338,7 @@ namespace Mono.Security.X509 {
                        // If privateKey it's available, load it too..
                        CspParameters cspParams = new CspParameters ();
                        cspParams.KeyContainerName = CryptoConvert.ToHex (cert.Hash);
-                       if (_storePath.StartsWith (X509StoreManager.LocalMachinePath))
+                       if (_storePath.StartsWith (X509StoreManager.LocalMachinePath) || _storePath.StartsWith(X509StoreManager.NewLocalMachinePath))
                                cspParams.Flags = CspProviderFlags.UseMachineKeyStore;
                        KeyPairPersistence kpp = new KeyPairPersistence (cspParams);