From 7174cdbfecc3b75945d9e2ef1f3e77d3cf322609 Mon Sep 17 00:00:00 2001 From: Ivan Naranjo Date: Thu, 22 Jun 2017 18:12:36 +0100 Subject: [PATCH] Master fixing 560 (#728) * Remove those credential files that cannot be decrypted. * Adding comments, handler for IOException. --- .../Accounts/WindowsCredentialsStore.cs | 40 +++++++++++++++++-- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/GoogleCloudExtension/GoogleCloudExtension/Accounts/WindowsCredentialsStore.cs b/GoogleCloudExtension/GoogleCloudExtension/Accounts/WindowsCredentialsStore.cs index e9d57e2f7..da97acdec 100644 --- a/GoogleCloudExtension/GoogleCloudExtension/Accounts/WindowsCredentialsStore.cs +++ b/GoogleCloudExtension/GoogleCloudExtension/Accounts/WindowsCredentialsStore.cs @@ -17,6 +17,7 @@ using GoogleCloudExtension.GCloud; using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Security.Cryptography; @@ -75,6 +76,7 @@ public IEnumerable GetCredentialsForInstance(Instanc result = Directory.EnumerateFiles(instanceStoragePath) .Where(x => Path.GetExtension(x) == PasswordFileExtension) .Select(x => LoadEncryptedCredentials(x)) + .Where(x => x != null) .OrderBy(x => x.User); } _credentialsForInstance[instancePath] = result; @@ -125,13 +127,43 @@ public string GetStoragePathForInstance(Instance instance) return Path.Combine(s_credentialsStoreRoot, instancePath); } + /// + /// Attempts to load and decrypt the credentials stored in and returns an + /// instance with the information stored in the file. If + /// the file cannot be loaded or decrypted it will return null. + /// + /// Note: The function will attempt to delete the file if it cannot be decrypted, this typically means that + /// the user's key is no longer valid. The function does not attempt to delete the file in case of a + /// since that will probably also throw again. + /// private WindowsInstanceCredentials LoadEncryptedCredentials(string path) { - var userName = GetUserName(path); - var encryptedPassword = File.ReadAllBytes(path); - var passwordBytes = ProtectedData.Unprotect(encryptedPassword, null, DataProtectionScope.CurrentUser); + try + { + var userName = GetUserName(path); + var encryptedPassword = File.ReadAllBytes(path); + var passwordBytes = ProtectedData.Unprotect(encryptedPassword, null, DataProtectionScope.CurrentUser); - return new WindowsInstanceCredentials { User = userName, Password = Encoding.UTF8.GetString(passwordBytes) }; + return new WindowsInstanceCredentials { User = userName, Password = Encoding.UTF8.GetString(passwordBytes) }; + } + catch (CryptographicException) + { + Debug.WriteLine($"Failed to decrypt credentials from: {path}"); + try + { + File.Delete(path); + } + catch (IOException) + { + Debug.WriteLine($"Failed cleaning corrupted credentials {path}"); + } + return null; + } + catch (IOException) + { + Debug.WriteLine($"Failed to load credentials from: {path}"); + return null; + } } private void SaveEncryptedCredentials(string path, WindowsInstanceCredentials credentials)