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:
David Sparer
2017-04-02 17:22:42 -06:00
parent fa5f423bbd
commit e886619b22
6 changed files with 98 additions and 104 deletions

View File

@@ -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);
}
}
}

View File

@@ -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>";
}
}
}

View File

@@ -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" />

View File

@@ -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;

View File

@@ -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);
}
}
}

View File

@@ -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>