mirror of
https://github.com/mRemoteNG/mRemoteNG.git
synced 2026-02-17 14:07:46 +08:00
added an Auth attribute to the xml cred file to get around an issue when the file contains no passwords
This commit is contained in:
23
mRemoteNGTests/Security/RandomGeneratorTests.cs
Normal file
23
mRemoteNGTests/Security/RandomGeneratorTests.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using mRemoteNG.Security;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace mRemoteNGTests.Security
|
||||
{
|
||||
public class RandomGeneratorTests
|
||||
{
|
||||
[Test]
|
||||
public void ProducesStringOfCorrectLength()
|
||||
{
|
||||
var text = RandomGenerator.RandomString(8);
|
||||
Assert.That(text.Length, Is.EqualTo(8));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void StringsDiffer()
|
||||
{
|
||||
var text1 = RandomGenerator.RandomString(8);
|
||||
var text2 = RandomGenerator.RandomString(8);
|
||||
Assert.That(text1, Is.Not.EqualTo(text2));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -145,6 +145,7 @@
|
||||
<Compile Include="Security\PasswordCreation\PasswordIncludesLowerCaseConstraintTests.cs" />
|
||||
<Compile Include="Security\PasswordCreation\PasswordIncludesNumbersConstraintTests.cs" />
|
||||
<Compile Include="Security\PasswordCreation\PasswordLengthConstraintTests.cs" />
|
||||
<Compile Include="Security\RandomGeneratorTests.cs" />
|
||||
<Compile Include="Security\SecureStringExtensionsTests.cs" />
|
||||
<Compile Include="Security\XmlCryptoProviderBuilderTests.cs" />
|
||||
<Compile Include="Tools\ExternalToolsArgumentParserTests.cs" />
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Security;
|
||||
using System.Xml.Linq;
|
||||
using mRemoteNG.Credential;
|
||||
using mRemoteNG.Security;
|
||||
using mRemoteNG.Security.Authentication;
|
||||
|
||||
|
||||
namespace mRemoteNG.Config.Serializers
|
||||
@@ -12,39 +13,42 @@ namespace mRemoteNG.Config.Serializers
|
||||
public class XmlCredentialDeserializer
|
||||
{
|
||||
public string SchemaVersion { get; } = "1.0";
|
||||
public IAuthenticator Authenticator { get; set; }
|
||||
|
||||
public IEnumerable<ICredentialRecord> Deserialize(string xml, SecureString decryptionKey)
|
||||
{
|
||||
try
|
||||
{
|
||||
var xdoc = XDocument.Parse(xml);
|
||||
ValidateSchemaVersion(xdoc);
|
||||
var cryptographyProvider = BuildCryptoProvider(xdoc.Root);
|
||||
var credentials = from element in xdoc.Descendants("Credential")
|
||||
select new CredentialRecord(Guid.Parse(element.Attribute("Id")?.Value))
|
||||
{
|
||||
Title = element.Attribute("Title")?.Value ?? "",
|
||||
Username = element.Attribute("Username")?.Value ?? "",
|
||||
Password =
|
||||
cryptographyProvider.Decrypt(element.Attribute("Password")?.Value, decryptionKey)
|
||||
.ConvertToSecureString(),
|
||||
Domain = element.Attribute("Domain")?.Value ?? ""
|
||||
};
|
||||
return credentials;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return new ICredentialRecord[0];
|
||||
}
|
||||
var xdoc = XDocument.Parse(xml);
|
||||
var rootElement = xdoc.Root;
|
||||
ValidateSchemaVersion(rootElement);
|
||||
var cryptographyProvider = BuildCryptoProvider(rootElement);
|
||||
Authenticate(rootElement, cryptographyProvider, decryptionKey);
|
||||
|
||||
var credentials = from element in xdoc.Descendants("Credential")
|
||||
select new CredentialRecord(Guid.Parse(element.Attribute("Id")?.Value))
|
||||
{
|
||||
Title = element.Attribute("Title")?.Value ?? "",
|
||||
Username = element.Attribute("Username")?.Value ?? "",
|
||||
Password =
|
||||
cryptographyProvider.Decrypt(element.Attribute("Password")?.Value, decryptionKey)
|
||||
.ConvertToSecureString(),
|
||||
Domain = element.Attribute("Domain")?.Value ?? ""
|
||||
};
|
||||
return credentials.ToArray();
|
||||
}
|
||||
|
||||
private void ValidateSchemaVersion(XDocument xdoc)
|
||||
private void ValidateSchemaVersion(XElement rootElement)
|
||||
{
|
||||
var docSchemaVersion = xdoc.Root?.Attribute("SchemaVersion")?.Value;
|
||||
var docSchemaVersion = rootElement?.Attribute("SchemaVersion")?.Value;
|
||||
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);
|
||||
}
|
||||
|
||||
private ICryptographyProvider BuildCryptoProvider(XElement rootElement)
|
||||
{
|
||||
if (rootElement == null)
|
||||
|
||||
@@ -29,6 +29,7 @@ namespace mRemoteNG.Config.Serializers
|
||||
new XAttribute("EncryptionEngine", _cryptographyProvider.CipherEngine),
|
||||
new XAttribute("BlockCipherMode", _cryptographyProvider.CipherMode),
|
||||
new XAttribute("KdfIterations", _cryptographyProvider.KeyDerivationIterations),
|
||||
new XAttribute("Auth", _cryptographyProvider.Encrypt(RandomGenerator.RandomString(30), encryptionKey)),
|
||||
new XAttribute("SchemaVersion", SchemaVersion),
|
||||
from r in credentialRecords
|
||||
select new XElement("Credential",
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
<xs:attribute name="BlockCipherMode" type="xs:string" use="required" />
|
||||
<xs:attribute name="KdfIterations" type="xs:int" use="optional" />
|
||||
<xs:attribute name="FullFileEncryption" type="xs:boolean" use="required" />
|
||||
<xs:attribute name="Auth" type="xs:string" use="required" />
|
||||
<xs:attribute name="SchemaVersion" type="xs:float" use="required" />
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
||||
25
mRemoteV1/Security/RandomGenerator.cs
Normal file
25
mRemoteV1/Security/RandomGenerator.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using Org.BouncyCastle.Security;
|
||||
|
||||
namespace mRemoteNG.Security
|
||||
{
|
||||
public class RandomGenerator
|
||||
{
|
||||
public static string RandomString(int length)
|
||||
{
|
||||
if (length < 0)
|
||||
throw new ArgumentException($"{nameof(length)} must be a positive integer");
|
||||
|
||||
var randomGen = new SecureRandom();
|
||||
var stringBuilder = new StringBuilder();
|
||||
const string availableChars = @"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789`~!@#$%^&*()-_=+|[]{};:',./<>?";
|
||||
for (var x = 0; x < length; x++)
|
||||
{
|
||||
var randomIndex = randomGen.Next(availableChars.Length - 1);
|
||||
stringBuilder.Append(availableChars[randomIndex]);
|
||||
}
|
||||
return stringBuilder.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -213,6 +213,7 @@
|
||||
<Compile Include="Credential\CredentialDeletionMsgBoxConfirmer.cs" />
|
||||
<Compile Include="Credential\CredentialDomainUserComparer.cs" />
|
||||
<Compile Include="Security\Authentication\IPasswordRequestor.cs" />
|
||||
<Compile Include="Security\RandomGenerator.cs" />
|
||||
<Compile Include="Tools\CustomCollections\IFullyNotifiableList.cs" />
|
||||
<Compile Include="Tools\CustomCollections\FullyObservableCollection.cs" />
|
||||
<Compile Include="Credential\CredentialRepositoryChangedArgs.cs" />
|
||||
|
||||
Reference in New Issue
Block a user