mirror of
https://github.com/mRemoteNG/mRemoteNG.git
synced 2026-02-17 22:11:48 +08:00
changed interface for loading credentials from a repo to get around issues with providing a key
This commit is contained in:
@@ -34,7 +34,7 @@ namespace mRemoteNG.Specs.Utilities
|
||||
new StaticSerializerKeyProviderDecorator<IEnumerable<ICredentialRecord>, string>(encryptor, encryptor) { Key = EncryptionKey }
|
||||
), new CredentialRecordLoader(
|
||||
dataProvider,
|
||||
new StaticDeserializerKeyProviderDecorator<string, IEnumerable<ICredentialRecord>>(decryptor, decryptor) { Key = EncryptionKey }
|
||||
decryptor
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Security;
|
||||
using mRemoteNG.Config;
|
||||
using mRemoteNG.Config.DataProviders;
|
||||
using mRemoteNG.Config.Serializers;
|
||||
@@ -12,29 +13,30 @@ namespace mRemoteNGTests.Config
|
||||
{
|
||||
private CredentialRecordLoader _credentialRecordLoader;
|
||||
private IDataProvider<string> _dataProvider;
|
||||
private IDeserializer<string, IEnumerable<ICredentialRecord>> _deserializer;
|
||||
private ISecureDeserializer<string, IEnumerable<ICredentialRecord>> _deserializer;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_dataProvider = Substitute.For<IDataProvider<string>>();
|
||||
_deserializer = Substitute.For<IDeserializer<string, IEnumerable<ICredentialRecord>>>();
|
||||
_deserializer = Substitute.For<ISecureDeserializer<string, IEnumerable<ICredentialRecord>>>();
|
||||
_credentialRecordLoader = new CredentialRecordLoader(_dataProvider, _deserializer);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void LoadsFromDataProvider()
|
||||
{
|
||||
_credentialRecordLoader.Load();
|
||||
_credentialRecordLoader.Load(new SecureString());
|
||||
_dataProvider.Received(1).Load();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DeserializesDataFromDataProvider()
|
||||
{
|
||||
var key = new SecureString();
|
||||
_dataProvider.Load().Returns("mydata");
|
||||
_credentialRecordLoader.Load();
|
||||
_deserializer.Received(1).Deserialize("mydata");
|
||||
_credentialRecordLoader.Load(key);
|
||||
_deserializer.Received(1).Deserialize("mydata", key);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,14 +17,14 @@ namespace mRemoteNGTests.Config.Serializers.CredentialSerializers
|
||||
public void Setup()
|
||||
{
|
||||
var baseDeserializer = new XmlCredentialRecordDeserializer();
|
||||
_sut = new XmlCredentialPasswordDecryptorDecorator(baseDeserializer) {Key = _decryptionKey};
|
||||
_sut = new XmlCredentialPasswordDecryptorDecorator(baseDeserializer);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OutputedCredentialHasDecryptedPassword()
|
||||
{
|
||||
var xml = GenerateXml();
|
||||
var output = _sut.Deserialize(xml);
|
||||
var output = _sut.Deserialize(xml, _decryptionKey);
|
||||
Assert.That(output.First().Password.ConvertToUnsecureString(), Is.EqualTo(_unencryptedPassword));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
using System.Security;
|
||||
using mRemoteNG.Config.Serializers;
|
||||
using mRemoteNG.Credential;
|
||||
using mRemoteNG.Security;
|
||||
using NSubstitute;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace mRemoteNGTests.Credential
|
||||
{
|
||||
public class StaticDeserializerKeyProviderDecoratorTests
|
||||
{
|
||||
private StaticDeserializerKeyProviderDecorator<object, string> _deserializerKeyProvider;
|
||||
private IDeserializer<object, string> _baseDeserializer;
|
||||
private IHasKey _objThatNeedsKey;
|
||||
private readonly SecureString _key = "someKey1".ConvertToSecureString();
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_objThatNeedsKey = Substitute.For<IHasKey>();
|
||||
_baseDeserializer = Substitute.For<IDeserializer<object, string>>();
|
||||
_deserializerKeyProvider = new StaticDeserializerKeyProviderDecorator<object, string>(_objThatNeedsKey, _baseDeserializer) { Key = _key };
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CallsBaseSerializer()
|
||||
{
|
||||
var creds = new[] { Substitute.For<ICredentialRecord>() };
|
||||
_deserializerKeyProvider.Deserialize(creds);
|
||||
_baseDeserializer.Received().Deserialize(creds);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PassesOnItsKey()
|
||||
{
|
||||
var creds = new[] { Substitute.For<ICredentialRecord>() };
|
||||
_deserializerKeyProvider.Deserialize(creds);
|
||||
Assert.That(_objThatNeedsKey.Key, Is.EqualTo(_deserializerKeyProvider.Key));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,21 +15,21 @@ namespace mRemoteNGTests.IntegrationTests
|
||||
public class XmlCredentialSerializerLifeCycleTests
|
||||
{
|
||||
private ISerializer<IEnumerable<ICredentialRecord>, string> _serializer;
|
||||
private IDeserializer<string, IEnumerable<ICredentialRecord>> _deserializer;
|
||||
private ISecureDeserializer<string, IEnumerable<ICredentialRecord>> _deserializer;
|
||||
private readonly Guid _id = Guid.NewGuid();
|
||||
private const string Title = "mycredential1";
|
||||
private const string Username = "user1";
|
||||
private const string Domain = "domain1";
|
||||
private readonly SecureString _password = "myPassword1!".ConvertToSecureString();
|
||||
private readonly SecureString _key = "myPassword1!".ConvertToSecureString();
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
var keyProvider = Substitute.For<IKeyProvider>();
|
||||
keyProvider.GetKey().Returns(_password);
|
||||
keyProvider.GetKey().Returns(_key);
|
||||
var cryptoProvider = new CryptoProviderFactory(BlockCipherEngines.AES, BlockCipherModes.CCM).Build();
|
||||
_serializer = new XmlCredentialPasswordEncryptorDecorator(cryptoProvider, new XmlCredentialRecordSerializer()) { Key = _password };
|
||||
_deserializer = new XmlCredentialPasswordDecryptorDecorator(new XmlCredentialRecordDeserializer()) { Key = _password };
|
||||
_serializer = new XmlCredentialPasswordEncryptorDecorator(cryptoProvider, new XmlCredentialRecordSerializer()) { Key = _key };
|
||||
_deserializer = new XmlCredentialPasswordDecryptorDecorator(new XmlCredentialRecordDeserializer());
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -37,7 +37,7 @@ namespace mRemoteNGTests.IntegrationTests
|
||||
{
|
||||
var credentials = new[] { new CredentialRecord(), new CredentialRecord() };
|
||||
var serializedCredentials = _serializer.Serialize(credentials);
|
||||
var deserializedCredentials = _deserializer.Deserialize(serializedCredentials);
|
||||
var deserializedCredentials = _deserializer.Deserialize(serializedCredentials, _key);
|
||||
Assert.That(deserializedCredentials.Count(), Is.EqualTo(2));
|
||||
}
|
||||
|
||||
@@ -73,17 +73,17 @@ namespace mRemoteNGTests.IntegrationTests
|
||||
public void PasswordConsistentAfterSerialization()
|
||||
{
|
||||
var sut = SerializeThenDeserializeCredential();
|
||||
Assert.That(sut.Password.ConvertToUnsecureString(), Is.EqualTo(_password.ConvertToUnsecureString()));
|
||||
Assert.That(sut.Password.ConvertToUnsecureString(), Is.EqualTo(_key.ConvertToUnsecureString()));
|
||||
}
|
||||
|
||||
private ICredentialRecord SerializeThenDeserializeCredential()
|
||||
{
|
||||
var credentials = new[]
|
||||
{
|
||||
new CredentialRecord(_id) {Title = Title, Username = Username, Domain = Domain, Password = _password}
|
||||
new CredentialRecord(_id) {Title = Title, Username = Username, Domain = Domain, Password = _key}
|
||||
};
|
||||
var serializedCredentials = _serializer.Serialize(credentials);
|
||||
var deserializedCredentials = _deserializer.Deserialize(serializedCredentials);
|
||||
var deserializedCredentials = _deserializer.Deserialize(serializedCredentials, _key);
|
||||
return deserializedCredentials.First();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,7 +137,6 @@
|
||||
<Compile Include="Credential\CredentialDomainUserComparerTests.cs" />
|
||||
<Compile Include="Credential\CredentialRepositoryListTests.cs" />
|
||||
<Compile Include="Credential\CredentialRecordTests.cs" />
|
||||
<Compile Include="Credential\StaticDeserializerKeyProviderDecoratorTests.cs" />
|
||||
<Compile Include="Credential\StaticSerializerKeyProviderDecoratorTests.cs" />
|
||||
<Compile Include="IntegrationTests\XmlCredentialSerializerLifeCycleTests.cs" />
|
||||
<Compile Include="IntegrationTests\XmlSerializationLifeCycleTests.cs" />
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace mRemoteNG.App.Initialization
|
||||
private readonly string _credentialRepoListPath = Path.Combine(SettingsFileInfo.SettingsPath, "credentialRepositories.xml");
|
||||
private readonly ICredentialRepositoryList _credentialRepositoryList;
|
||||
private readonly ISerializer<IEnumerable<ICredentialRecord>, string> _credRepoSerializer;
|
||||
private readonly IDeserializer<string, IEnumerable<ICredentialRecord>> _credRepoDeserializer;
|
||||
private readonly ISecureDeserializer<string, IEnumerable<ICredentialRecord>> _credRepoDeserializer;
|
||||
private readonly string _credentialFilePath;
|
||||
|
||||
public CredsAndConsSetup(ICredentialRepositoryList credentialRepositoryList, string credentialFilePath)
|
||||
|
||||
@@ -11,9 +11,9 @@ namespace mRemoteNG.Config
|
||||
public class CredentialRecordLoader
|
||||
{
|
||||
private readonly IDataProvider<string> _dataProvider;
|
||||
private readonly IDeserializer<string, IEnumerable<ICredentialRecord>> _deserializer;
|
||||
private readonly ISecureDeserializer<string, IEnumerable<ICredentialRecord>> _deserializer;
|
||||
|
||||
public CredentialRecordLoader(IDataProvider<string> dataProvider, IDeserializer<string, IEnumerable<ICredentialRecord>> deserializer)
|
||||
public CredentialRecordLoader(IDataProvider<string> dataProvider, ISecureDeserializer<string, IEnumerable<ICredentialRecord>> deserializer)
|
||||
{
|
||||
if (dataProvider == null)
|
||||
throw new ArgumentNullException(nameof(dataProvider));
|
||||
@@ -24,10 +24,10 @@ namespace mRemoteNG.Config
|
||||
_deserializer = deserializer;
|
||||
}
|
||||
|
||||
public IEnumerable<ICredentialRecord> Load()
|
||||
public IEnumerable<ICredentialRecord> Load(SecureString key)
|
||||
{
|
||||
var serializedCredentials = _dataProvider.Load();
|
||||
return _deserializer.Deserialize(serializedCredentials);
|
||||
return _deserializer.Deserialize(serializedCredentials, key);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,9 +10,9 @@ namespace mRemoteNG.Config.Serializers.CredentialProviderSerializer
|
||||
public class CredentialRepositoryListDeserializer
|
||||
{
|
||||
private readonly ISerializer<IEnumerable<ICredentialRecord>, string> _serializer;
|
||||
private readonly IDeserializer<string, IEnumerable<ICredentialRecord>> _deserializer;
|
||||
private readonly ISecureDeserializer<string, IEnumerable<ICredentialRecord>> _deserializer;
|
||||
|
||||
public CredentialRepositoryListDeserializer(ISerializer<IEnumerable<ICredentialRecord>, string> serializer, IDeserializer<string, IEnumerable<ICredentialRecord>> deserializer)
|
||||
public CredentialRepositoryListDeserializer(ISerializer<IEnumerable<ICredentialRecord>, string> serializer, ISecureDeserializer<string, IEnumerable<ICredentialRecord>> deserializer)
|
||||
{
|
||||
if (serializer == null)
|
||||
throw new ArgumentNullException(nameof(serializer));
|
||||
|
||||
@@ -3,25 +3,13 @@ using System.Collections.Generic;
|
||||
using System.Security;
|
||||
using System.Xml.Linq;
|
||||
using mRemoteNG.Credential;
|
||||
using mRemoteNG.Security;
|
||||
using mRemoteNG.Security.Factories;
|
||||
|
||||
namespace mRemoteNG.Config.Serializers.CredentialSerializer
|
||||
{
|
||||
public class XmlCredentialPasswordDecryptorDecorator : IDeserializer<string, IEnumerable<ICredentialRecord>>, IHasKey
|
||||
public class XmlCredentialPasswordDecryptorDecorator : ISecureDeserializer<string, IEnumerable<ICredentialRecord>>
|
||||
{
|
||||
private readonly IDeserializer<string, IEnumerable<ICredentialRecord>> _baseDeserializer;
|
||||
private SecureString _decryptionKey = new SecureString();
|
||||
|
||||
public SecureString Key
|
||||
{
|
||||
get { return _decryptionKey; }
|
||||
set
|
||||
{
|
||||
if (value == null) return;
|
||||
_decryptionKey = value;
|
||||
}
|
||||
}
|
||||
|
||||
public XmlCredentialPasswordDecryptorDecorator(IDeserializer<string, IEnumerable<ICredentialRecord>> baseDeserializer)
|
||||
{
|
||||
@@ -31,13 +19,13 @@ namespace mRemoteNG.Config.Serializers.CredentialSerializer
|
||||
_baseDeserializer = baseDeserializer;
|
||||
}
|
||||
|
||||
public IEnumerable<ICredentialRecord> Deserialize(string xml)
|
||||
public IEnumerable<ICredentialRecord> Deserialize(string xml, SecureString key)
|
||||
{
|
||||
var decryptedXml = DecryptPasswords(xml);
|
||||
var decryptedXml = DecryptPasswords(xml, key);
|
||||
return _baseDeserializer.Deserialize(decryptedXml);
|
||||
}
|
||||
|
||||
private string DecryptPasswords(string xml)
|
||||
private string DecryptPasswords(string xml, SecureString key)
|
||||
{
|
||||
var xdoc = XDocument.Parse(xml);
|
||||
var cryptoProvider = new CryptoProviderFactoryFromXml(xdoc.Root).Build();
|
||||
@@ -45,7 +33,7 @@ namespace mRemoteNG.Config.Serializers.CredentialSerializer
|
||||
{
|
||||
var passwordAttribute = credentialElement.Attribute("Password");
|
||||
if (passwordAttribute == null) continue;
|
||||
var decryptedPassword = cryptoProvider.Decrypt(passwordAttribute.Value, _decryptionKey);
|
||||
var decryptedPassword = cryptoProvider.Decrypt(passwordAttribute.Value, key);
|
||||
passwordAttribute.SetValue(decryptedPassword);
|
||||
}
|
||||
return xdoc.ToString();
|
||||
|
||||
9
mRemoteV1/Config/Serializers/ISecureDeserializer.cs
Normal file
9
mRemoteV1/Config/Serializers/ISecureDeserializer.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using System.Security;
|
||||
|
||||
namespace mRemoteNG.Config.Serializers
|
||||
{
|
||||
public interface ISecureDeserializer<in TIn, out TOut>
|
||||
{
|
||||
TOut Deserialize(TIn serializedData, SecureString key);
|
||||
}
|
||||
}
|
||||
@@ -10,9 +10,9 @@ namespace mRemoteNG.Credential.Repositories
|
||||
public class CredentialRepositoryFactory
|
||||
{
|
||||
private readonly ISerializer<IEnumerable<ICredentialRecord>, string> _serializer;
|
||||
private readonly IDeserializer<string, IEnumerable<ICredentialRecord>> _deserializer;
|
||||
private readonly ISecureDeserializer<string, IEnumerable<ICredentialRecord>> _deserializer;
|
||||
|
||||
public CredentialRepositoryFactory(ISerializer<IEnumerable<ICredentialRecord>, string> serializer, IDeserializer<string, IEnumerable<ICredentialRecord>> deserializer)
|
||||
public CredentialRepositoryFactory(ISerializer<IEnumerable<ICredentialRecord>, string> serializer, ISecureDeserializer<string, IEnumerable<ICredentialRecord>> deserializer)
|
||||
{
|
||||
if (serializer == null)
|
||||
throw new ArgumentNullException(nameof(serializer));
|
||||
|
||||
@@ -3,11 +3,7 @@ using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using mRemoteNG.Config;
|
||||
using mRemoteNG.Config.DataProviders;
|
||||
using mRemoteNG.Config.Serializers.CredentialSerializer;
|
||||
using mRemoteNG.Security;
|
||||
using mRemoteNG.Tools.CustomCollections;
|
||||
using mRemoteNG.UI.Forms;
|
||||
|
||||
namespace mRemoteNG.Credential.Repositories
|
||||
{
|
||||
@@ -39,7 +35,7 @@ namespace mRemoteNG.Credential.Repositories
|
||||
|
||||
public void LoadCredentials()
|
||||
{
|
||||
var credentials = _credentialRecordLoader.Load();
|
||||
var credentials = _credentialRecordLoader.Load(Config.Key);
|
||||
foreach (var newCredential in credentials)
|
||||
{
|
||||
if (ThisIsADuplicateCredentialRecord(newCredential)) continue;
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
using System;
|
||||
using System.Security;
|
||||
using mRemoteNG.Config.Serializers;
|
||||
using mRemoteNG.Security;
|
||||
|
||||
namespace mRemoteNG.Credential
|
||||
{
|
||||
public class StaticDeserializerKeyProviderDecorator<TIn, TOut> : IDeserializer<TIn, TOut>, IHasKey
|
||||
{
|
||||
private readonly IDeserializer<TIn, TOut> _baseDeserializer;
|
||||
private readonly IHasKey _objThatNeedsKey;
|
||||
private SecureString _key = new SecureString();
|
||||
|
||||
public SecureString Key
|
||||
{
|
||||
get { return _key; }
|
||||
set
|
||||
{
|
||||
if (value == null) return;
|
||||
_key = value;
|
||||
}
|
||||
}
|
||||
|
||||
public StaticDeserializerKeyProviderDecorator(IHasKey objThatNeedsKey, IDeserializer<TIn, TOut> baseDeserializer)
|
||||
{
|
||||
if (objThatNeedsKey == null)
|
||||
throw new ArgumentNullException(nameof(objThatNeedsKey));
|
||||
if (baseDeserializer == null)
|
||||
throw new ArgumentNullException(nameof(baseDeserializer));
|
||||
|
||||
_objThatNeedsKey = objThatNeedsKey;
|
||||
_baseDeserializer = baseDeserializer;
|
||||
}
|
||||
|
||||
public TOut Deserialize(TIn serializedData)
|
||||
{
|
||||
_objThatNeedsKey.Key = Key;
|
||||
return _baseDeserializer.Deserialize(serializedData);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -145,6 +145,7 @@
|
||||
<Compile Include="Config\CredentialRepositoryListLoader.cs" />
|
||||
<Compile Include="Config\Serializers\CredentialSerializer\XmlCredentialPasswordDecryptorDecorator.cs" />
|
||||
<Compile Include="Config\Serializers\CredentialSerializer\XmlCredentialPasswordEncryptorDecorator.cs" />
|
||||
<Compile Include="Config\Serializers\ISecureDeserializer.cs" />
|
||||
<Compile Include="Config\Serializers\MiscSerializers\ActiveDirectoryDeserializer.cs" />
|
||||
<Compile Include="Config\Serializers\CredentialProviderSerializer\CredentialRepositoryListSerializer.cs" />
|
||||
<Compile Include="Config\Serializers\MiscSerializers\CsvConnectionsSerializerMremotengFormat.cs" />
|
||||
@@ -215,7 +216,6 @@
|
||||
<Compile Include="Credential\CredentialChangedEventArgs.cs" />
|
||||
<Compile Include="Credential\CredentialDeletionMsgBoxConfirmer.cs" />
|
||||
<Compile Include="Credential\CredentialDomainUserComparer.cs" />
|
||||
<Compile Include="Credential\StaticDeserializerKeyProviderDecorator.cs" />
|
||||
<Compile Include="Credential\StaticSerializerKeyProviderDecorator.cs" />
|
||||
<Compile Include="Security\Factories\CryptoProviderFactoryFromSettings.cs" />
|
||||
<Compile Include="Security\Factories\LegacyInsecureCryptoProviderFactory.cs" />
|
||||
|
||||
Reference in New Issue
Block a user