mirror of
https://github.com/mRemoteNG/mRemoteNG.git
synced 2026-02-17 22:11:48 +08:00
simplified the implementation of the xml cred deserializer
removed anything to do with encryption which will be handled by decorators
This commit is contained in:
@@ -1,85 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Security;
|
||||
using mRemoteNG.Config.Serializers;
|
||||
using mRemoteNG.Security;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace mRemoteNGTests.Config.Serializers.CredentialSerializers
|
||||
{
|
||||
public class XmlCredentialDeserializerTests
|
||||
{
|
||||
private XmlCredentialRecordDeserializer _deserializer;
|
||||
private ICryptographyProvider _cryptographyProvider;
|
||||
private readonly SecureString _key = "myencrptionpass".ConvertToSecureString();
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_cryptographyProvider = new CryptographyProviderFactory().CreateAeadCryptographyProvider(BlockCipherEngines.AES, BlockCipherModes.GCM);
|
||||
_deserializer = new XmlCredentialRecordDeserializer();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void HasCorrectId()
|
||||
{
|
||||
var id = Guid.NewGuid();
|
||||
var xml = $"<Credentials EncryptionEngine=\"AES\" BlockCipherMode=\"GCM\" KdfIterations=\"1000\" SchemaVersion=\"1.0\">\r\n <Credential Id=\"{id}\" Title=\"testcred\" Username=\"myuser\" Password=\"{GeneratePass("abc")}\" />\r\n</Credentials>";
|
||||
var creds = _deserializer.Deserialize(xml, _key);
|
||||
Assert.That(creds.First().Id, Is.EqualTo(id));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void HasCorrectTitle()
|
||||
{
|
||||
const string title = "testtitle";
|
||||
var xml = $"<Credentials EncryptionEngine=\"AES\" BlockCipherMode=\"GCM\" KdfIterations=\"1000\" SchemaVersion=\"1.0\">\r\n <Credential Id=\"256f4c8c-5819-4226-ad55-6f1f341b5449\" Title=\"{title}\" Username=\"myuser\" Password=\"{GeneratePass("abc")}\" />\r\n</Credentials>";
|
||||
var creds = _deserializer.Deserialize(xml, _key);
|
||||
Assert.That(creds.First().Title, Is.EqualTo(title));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void HasCorrectUsername()
|
||||
{
|
||||
const string username = "myuser";
|
||||
var xml = $"<Credentials EncryptionEngine=\"AES\" BlockCipherMode=\"GCM\" KdfIterations=\"1000\" SchemaVersion=\"1.0\">\r\n <Credential Id=\"256f4c8c-5819-4226-ad55-6f1f341b5449\" Title=\"testtitle\" Username=\"{username}\" Password=\"{GeneratePass("abc")}\" />\r\n</Credentials>";
|
||||
var creds = _deserializer.Deserialize(xml, _key);
|
||||
Assert.That(creds.First().Username, Is.EqualTo(username));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void HasCorrectPassword()
|
||||
{
|
||||
const string plaintextPassword = "mypassword";
|
||||
var xml = $"<Credentials EncryptionEngine=\"AES\" BlockCipherMode=\"GCM\" KdfIterations=\"1000\" SchemaVersion=\"1.0\">\r\n <Credential Id=\"256f4c8c-5819-4226-ad55-6f1f341b5449\" Title=\"testtitle\" Username=\"myuser\" Password=\"{GeneratePass(plaintextPassword)}\" />\r\n</Credentials>";
|
||||
var creds = _deserializer.Deserialize(xml, _key);
|
||||
Assert.That(creds.First().Password.ConvertToUnsecureString(), Is.EqualTo(plaintextPassword));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DeserializesAllCredentials()
|
||||
{
|
||||
var xml = $"<Credentials EncryptionEngine=\"AES\" BlockCipherMode=\"GCM\" KdfIterations=\"1000\" SchemaVersion=\"1.0\">\r\n <Credential Id=\"256f4c8c-5819-4226-ad55-6f1f341b5449\" Title=\"testtitle\" Username=\"myuser\" Password=\"{GeneratePass("abc")}\" />\r\n <Credential Id=\"356f4c8c-5819-4226-ad55-6f1f341b5449\" Title=\"othertitle\" Username=\"someuser\" Password=\"{GeneratePass("abc")}\" />\r\n</Credentials>";
|
||||
var creds = _deserializer.Deserialize(xml, _key);
|
||||
Assert.That(creds.Count(), Is.EqualTo(2));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanDecryptNonStandardEncryptions()
|
||||
{
|
||||
var otherCryptoProvider = new CryptographyProviderFactory().CreateAeadCryptographyProvider(BlockCipherEngines.Serpent, BlockCipherModes.CCM);
|
||||
otherCryptoProvider.KeyDerivationIterations = 2000;
|
||||
const string plaintextPassword = "mypassword";
|
||||
var encryptedPassword = otherCryptoProvider.Encrypt(plaintextPassword, _key);
|
||||
var xml =
|
||||
$"<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Credentials EncryptionEngine=\"Serpent\" BlockCipherMode=\"CCM\" KdfIterations=\"2000\" SchemaVersion=\"1.0\">\r\n <Credential Id=\"faadd345-6c68-4891-9897-d22525ec7c58\" Title=\"testcred\" Username=\"davids\" Password=\"{encryptedPassword}\" />\r\n</Credentials>";
|
||||
var creds = _deserializer.Deserialize(xml, _key);
|
||||
Assert.That(creds.First().Password.ConvertToUnsecureString(), Is.EqualTo(plaintextPassword));
|
||||
}
|
||||
|
||||
private string GeneratePass(string plaintext)
|
||||
{
|
||||
return _cryptographyProvider.Encrypt(plaintext, _key);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Security;
|
||||
using mRemoteNG.Config.Serializers.CredentialSerializer;
|
||||
using mRemoteNG.Security;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace mRemoteNGTests.Config.Serializers.CredentialSerializers
|
||||
{
|
||||
public class XmlCredentialRecordDeserializerTests
|
||||
{
|
||||
private XmlCredentialRecordDeserializer _deserializer;
|
||||
private readonly Guid _id = Guid.NewGuid();
|
||||
private const string Title = "sometitle";
|
||||
private const string Username = "myusername";
|
||||
private const string Domain = "mydomain";
|
||||
private const string PlaintextPassword = "mypassword";
|
||||
private readonly SecureString _key = "myencrptionpass".ConvertToSecureString();
|
||||
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_deserializer = new XmlCredentialRecordDeserializer();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void HasCorrectId()
|
||||
{
|
||||
var xml = GenerateXml();
|
||||
var creds = _deserializer.Deserialize(xml, _key);
|
||||
Assert.That(creds.First().Id, Is.EqualTo(_id));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void HasCorrectTitle()
|
||||
{
|
||||
var xml = GenerateXml();
|
||||
var creds = _deserializer.Deserialize(xml, _key);
|
||||
Assert.That(creds.First().Title, Is.EqualTo(Title));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void HasCorrectUsername()
|
||||
{
|
||||
var xml = GenerateXml();
|
||||
var creds = _deserializer.Deserialize(xml, _key);
|
||||
Assert.That(creds.First().Username, Is.EqualTo(Username));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void HasCorrectDomain()
|
||||
{
|
||||
var xml = GenerateXml();
|
||||
var creds = _deserializer.Deserialize(xml, _key);
|
||||
Assert.That(creds.First().Domain, Is.EqualTo(Domain));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void HasCorrectPassword()
|
||||
{
|
||||
var xml = GenerateXml();
|
||||
var creds = _deserializer.Deserialize(xml, _key);
|
||||
Assert.That(creds.First().Password.ConvertToUnsecureString(), Is.EqualTo(PlaintextPassword));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DeserializesAllCredentials()
|
||||
{
|
||||
var xml = GenerateXml();
|
||||
var creds = _deserializer.Deserialize(xml, _key);
|
||||
Assert.That(creds.Count(), Is.EqualTo(2));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanDecryptNonStandardEncryptions()
|
||||
{
|
||||
var xml = GenerateXml(BlockCipherEngines.Serpent, BlockCipherModes.EAX, 3000);
|
||||
var creds = _deserializer.Deserialize(xml, _key);
|
||||
Assert.That(creds.First().Password.ConvertToUnsecureString(), Is.EqualTo(PlaintextPassword));
|
||||
}
|
||||
|
||||
|
||||
private string GenerateXml(BlockCipherEngines engine = BlockCipherEngines.AES, BlockCipherModes mode = BlockCipherModes.GCM, int interations = 1000)
|
||||
{
|
||||
return $"<Credentials EncryptionEngine=\"{engine}\" BlockCipherMode=\"{mode}\" KdfIterations=\"{interations}\" SchemaVersion=\"1.0\">" +
|
||||
$"<Credential Id=\"{_id}\" Title=\"{Title}\" Username=\"{Username}\" Domain=\"{Domain}\" Password=\"{PlaintextPassword}\" />" +
|
||||
$"<Credential Id=\"{Guid.NewGuid()}\" Title=\"{Title}\" Username=\"{Username}\" Domain=\"{Domain}\" Password=\"{PlaintextPassword}\" />" +
|
||||
"</Credentials>";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -125,7 +125,7 @@
|
||||
<Compile Include="Config\Serializers\ConnectionSerializers\XmlConnectionsDocumentCompilerTests.cs" />
|
||||
<Compile Include="Config\Serializers\ConnectionSerializers\XmlConnectionsDocumentEncryptorTests.cs" />
|
||||
<Compile Include="Config\Serializers\ConnectionSerializers\XmlConnectionsSerializerTests.cs" />
|
||||
<Compile Include="Config\Serializers\CredentialSerializers\XmlCredentialDeserializerTests.cs" />
|
||||
<Compile Include="Config\Serializers\CredentialSerializers\XmlCredentialRecordDeserializerTests.cs" />
|
||||
<Compile Include="Config\Serializers\CredentialSerializers\XmlCredentialSerializerTests.cs" />
|
||||
<Compile Include="Config\Serializers\ConnectionSerializers\XmlRootNodeSerializerTests.cs" />
|
||||
<Compile Include="Connection\AbstractConnectionInfoDataTests.cs" />
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Security;
|
||||
using mRemoteNG.Config.DataProviders;
|
||||
using mRemoteNG.Config.Serializers;
|
||||
using mRemoteNG.Config.Serializers.CredentialSerializer;
|
||||
using mRemoteNG.Credential;
|
||||
|
||||
|
||||
|
||||
@@ -5,32 +5,25 @@ using System.Security;
|
||||
using System.Xml.Linq;
|
||||
using mRemoteNG.Credential;
|
||||
using mRemoteNG.Security;
|
||||
using mRemoteNG.Security.Authentication;
|
||||
|
||||
|
||||
namespace mRemoteNG.Config.Serializers
|
||||
namespace mRemoteNG.Config.Serializers.CredentialSerializer
|
||||
{
|
||||
public class XmlCredentialRecordDeserializer
|
||||
{
|
||||
public string SchemaVersion { get; } = "1.0";
|
||||
public IAuthenticator Authenticator { get; set; }
|
||||
|
||||
public IEnumerable<ICredentialRecord> Deserialize(string xml, SecureString decryptionKey)
|
||||
{
|
||||
var xdoc = XDocument.Parse(xml);
|
||||
var rootElement = xdoc.Root;
|
||||
ValidateSchemaVersion(rootElement);
|
||||
var cryptographyProvider = CryptographyProviderFactory.BuildFromXml(rootElement);
|
||||
Authenticate(rootElement, cryptographyProvider, decryptionKey);
|
||||
|
||||
var credentials = from element in xdoc.Descendants("Credential")
|
||||
select new CredentialRecord(Guid.Parse(element.Attribute("Id")?.Value))
|
||||
select new CredentialRecord(Guid.Parse(element.Attribute("Id")?.Value ?? Guid.NewGuid().ToString()))
|
||||
{
|
||||
Title = element.Attribute("Title")?.Value ?? "",
|
||||
Username = element.Attribute("Username")?.Value ?? "",
|
||||
Password =
|
||||
cryptographyProvider.Decrypt(element.Attribute("Password")?.Value, decryptionKey)
|
||||
.ConvertToSecureString(),
|
||||
Password = element.Attribute("Password")?.Value.ConvertToSecureString(),
|
||||
Domain = element.Attribute("Domain")?.Value ?? ""
|
||||
};
|
||||
return credentials.ToArray();
|
||||
@@ -42,11 +35,5 @@ namespace mRemoteNG.Config.Serializers
|
||||
if (docSchemaVersion != SchemaVersion)
|
||||
throw new Exception($"The schema version of this document is not supported by this class. Document Version: {docSchemaVersion} Supported Version: {SchemaVersion}");
|
||||
}
|
||||
|
||||
private void Authenticate(XElement rootElement, ICryptographyProvider cryptographyProvider, SecureString key)
|
||||
{
|
||||
var authString = rootElement.Attribute("Auth")?.Value;
|
||||
cryptographyProvider.Decrypt(authString, key);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=config_005Cserializers_005Cconnectionserializers/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=config_005Cserializers_005Ccredentialserializer/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=config_005Cserializers_005Ccredentialserializer/@EntryIndexedValue">False</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=config_005Cserializers_005Cexportserializers/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=config_005Cserializers_005Cexternalserializers/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=config_005Cserializers_005Cmiscserializers/@EntryIndexedValue">True</s:Boolean>
|
||||
|
||||
Reference in New Issue
Block a user