Merge pull request #2621 from magriggs/issue-726

Issue 726 - SecureString for ConnectionInfo.Password
This commit is contained in:
Dimitrij
2024-07-29 09:05:05 +01:00
committed by GitHub
30 changed files with 203 additions and 47 deletions

View File

@@ -8,6 +8,7 @@ using mRemoteNG.Connection.Protocol.Http;
using mRemoteNG.Connection.Protocol.RDP;
using mRemoteNG.Connection.Protocol.VNC;
using mRemoteNG.Container;
using mRemoteNG.Security;
using mRemoteNG.Tree;
using mRemoteNG.Tree.Root;
@@ -112,8 +113,8 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Csv
: "";
connectionRecord.Password = headers.Contains("Password")
? connectionCsv[headers.IndexOf("Password")]
: "";
? connectionCsv[headers.IndexOf("Password")].ConvertToSecureString()
: "".ConvertToSecureString();
connectionRecord.Domain = headers.Contains("Domain")
? connectionCsv[headers.IndexOf("Domain")]

View File

@@ -112,7 +112,7 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Csv
sb.Append(FormatForCsv(con.Username));
if (_saveFilter.SavePassword)
sb.Append(FormatForCsv(con.Password));
sb.Append(con.Password?.ConvertToUnsecureString() + ";");
if (_saveFilter.SaveDomain)
sb.Append(FormatForCsv(con.Domain));

View File

@@ -7,6 +7,7 @@ using System.Runtime.Versioning;
using mRemoteNG.Connection;
using mRemoteNG.Connection.Protocol;
using mRemoteNG.Container;
using mRemoteNG.Security;
using mRemoteNG.Tree;
#endregion
@@ -130,7 +131,7 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Csv.RemoteDesktopMa
Hostname = hostString,
Port = port,
Username = username,
Password = password,
Password = password?.ConvertToSecureString(),
Domain = domain,
Icon = connectionType.IconName ?? "mRemoteNG",
Description = description,

View File

@@ -4,6 +4,7 @@ using System.Data;
using System.Linq;
using System.Runtime.Versioning;
using System.Security;
using System.Windows.Media.TextFormatting;
using mRemoteNG.App;
using mRemoteNG.Connection;
using mRemoteNG.Connection.Protocol;
@@ -111,7 +112,8 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Sql
connectionInfo.OpeningCommand = (string)dataRow["OpeningCommand"];
connectionInfo.OpeningCommand = (string)dataRow["OpeningCommand"];
connectionInfo.Panel = (string)dataRow["Panel"];
connectionInfo.Password = DecryptValue((string)dataRow["Password"]);
var pw = dataRow["Password"] as string;
connectionInfo.Password = DecryptValue(pw ?? "").ConvertToSecureString();
connectionInfo.Port = (int)dataRow["Port"];
connectionInfo.PostExtApp = (string)dataRow["PostExtApp"];
connectionInfo.PreExtApp = (string)dataRow["PreExtApp"];

View File

@@ -519,7 +519,7 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Sql
dataRow["InheritVNCViewOnly"].Equals(false);
}
bool pwd = dataRow["Password"].Equals(_saveFilter.SavePassword ? _cryptographyProvider.Encrypt(connectionInfo.Password, _encryptionKey) : "") &&
bool pwd = dataRow["Password"].Equals(_saveFilter.SavePassword ? _cryptographyProvider.Encrypt(connectionInfo.Password?.ConvertToUnsecureString(), _encryptionKey) : "") &&
dataRow["VNCProxyPassword"].Equals(_cryptographyProvider.Encrypt(connectionInfo.VNCProxyPassword, _encryptionKey)) &&
dataRow["RDGatewayPassword"].Equals(_cryptographyProvider.Encrypt(connectionInfo.RDGatewayPassword, _encryptionKey));
return !(pwd && isFieldNotChange && isInheritanceFieldNotChange);
@@ -575,7 +575,7 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Sql
dataRow["OpeningCommand"] = connectionInfo.OpeningCommand;
dataRow["Panel"] = connectionInfo.Panel;
dataRow["ParentID"] = connectionInfo.Parent?.ConstantID ?? "";
dataRow["Password"] = _saveFilter.SavePassword ? _cryptographyProvider.Encrypt(connectionInfo.Password, _encryptionKey) : "";
dataRow["Password"] = _saveFilter.SavePassword ? _cryptographyProvider.Encrypt(connectionInfo.Password?.ConvertToUnsecureString(), _encryptionKey) : "";
dataRow["Port"] = connectionInfo.Port;
dataRow["PositionID"] = _currentNodeIndex;
dataRow["PostExtApp"] = connectionInfo.PostExtApp;

View File

@@ -61,7 +61,7 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Xml
: new XAttribute("Domain", ""));
if (_saveFilter.SavePassword && !connectionInfo.Inheritance.Password)
element.Add(new XAttribute("Password", _cryptographyProvider.Encrypt(connectionInfo.Password, _encryptionKey)));
element.Add(new XAttribute("Password", _cryptographyProvider.Encrypt(connectionInfo.Password.ConvertToUnsecureString(), _encryptionKey)));
else
element.Add(new XAttribute("Password", ""));

View File

@@ -62,7 +62,7 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Xml
: new XAttribute("Domain", ""));
if (_saveFilter.SavePassword && !connectionInfo.Inheritance.Password)
element.Add(new XAttribute("Password", _cryptographyProvider.Encrypt(connectionInfo.Password, _encryptionKey)));
element.Add(new XAttribute("Password", _cryptographyProvider.Encrypt(connectionInfo.Password.ConvertToUnsecureString(), _encryptionKey)));
else
element.Add(new XAttribute("Password", ""));
}

View File

@@ -62,7 +62,7 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Xml
: new XAttribute("Domain", ""));
if (_saveFilter.SavePassword && !connectionInfo.Inheritance.Password)
element.Add(new XAttribute("Password", _cryptographyProvider.Encrypt(connectionInfo.Password, _encryptionKey)));
element.Add(new XAttribute("Password", _cryptographyProvider.Encrypt(connectionInfo.Password?.ConvertToUnsecureString(), _encryptionKey)));
else
element.Add(new XAttribute("Password", ""));
}

View File

@@ -218,7 +218,7 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Xml
{
connectionInfo.Username = xmlnode.GetAttributeAsString("Username");
//connectionInfo.Password = _decryptor.Decrypt(xmlnode.GetAttributeAsString("Password"));
connectionInfo.Password = _decryptor.Decrypt(xmlnode.GetAttributeAsString("Password"));
connectionInfo.Password = _decryptor.Decrypt(xmlnode.GetAttributeAsString("Password")).ConvertToSecureString();
connectionInfo.Domain = xmlnode.GetAttributeAsString("Domain");
}
}

View File

@@ -5,6 +5,7 @@ using System.Xml;
using mRemoteNG.Connection;
using mRemoteNG.Connection.Protocol;
using mRemoteNG.Container;
using mRemoteNG.Security;
using mRemoteNG.Tree;
using mRemoteNG.Tree.Root;
@@ -133,7 +134,7 @@ namespace mRemoteNG.Config.Serializers.MiscSerializers
XmlNode loginNode = xmlNode.SelectSingleNode("./login");
connectionInfo.Username = loginNode?.SelectSingleNode("login")?.InnerText;
connectionInfo.Password = loginNode?.SelectSingleNode("password")?.InnerText;
connectionInfo.Password = loginNode?.SelectSingleNode("password")?.InnerText.ConvertToSecureString();
// ./prompt
// ./timeout/connectiontimeout

View File

@@ -11,6 +11,7 @@ using mRemoteNG.Tree;
using mRemoteNG.Tree.Root;
using mRemoteNG.Resources.Language;
using System.Runtime.Versioning;
using mRemoteNG.Security;
namespace mRemoteNG.Config.Serializers.MiscSerializers
{
@@ -163,12 +164,12 @@ namespace mRemoteNG.Config.Serializers.MiscSerializers
if (_schemaVersion == 1) // Version 2.2 allows clear text passwords
{
connectionInfo.Password = passwordNode?.Attributes?["storeAsClearText"]?.Value == "True"
? passwordNode.InnerText
: DecryptRdcManPassword(passwordNode?.InnerText);
? passwordNode.InnerText.ConvertToSecureString()
: DecryptRdcManPassword(passwordNode?.InnerText).ConvertToSecureString();
}
else
{
connectionInfo.Password = DecryptRdcManPassword(passwordNode?.InnerText);
connectionInfo.Password = DecryptRdcManPassword(passwordNode?.InnerText).ConvertToSecureString();
}
connectionInfo.Domain = logonCredentialsNode.SelectSingleNode("./domain")?.InnerText ?? string.Empty;

View File

@@ -9,6 +9,7 @@ using mRemoteNG.Tools;
using mRemoteNG.Tools.Attributes;
using mRemoteNG.Resources.Language;
using System.Runtime.Versioning;
using System.Security;
namespace mRemoteNG.Connection
{
@@ -29,7 +30,7 @@ namespace mRemoteNG.Connection
private ExternalCredentialProvider _externalCredentialProvider;
private string _userViaAPI = "";
private string _username = "";
private string _password = "";
private SecureString _password = null;
private string _domain = "";
private string _vmId = "";
private bool _useEnhancedMode;
@@ -213,7 +214,7 @@ namespace mRemoteNG.Connection
LocalizedAttributes.LocalizedDescription(nameof(Language.PropertyDescriptionPassword)),
PasswordPropertyText(true),
AttributeUsedInAllProtocolsExcept(ProtocolType.Telnet, ProtocolType.Rlogin, ProtocolType.RAW)]
public virtual string Password
public virtual SecureString Password
{
get => GetPropertyValue("Password", _password);
set => SetField(ref _password, value, "Password");

View File

@@ -1,6 +1,7 @@
using mRemoteNG.App;
using mRemoteNG.Messages;
using mRemoteNG.Resources.Language;
using mRemoteNG.Security;
using mRemoteNG.Security.SymmetricEncryption;
using mRemoteNG.Tools;
using mRemoteNG.Tools.Cmdline;
@@ -101,7 +102,7 @@ namespace mRemoteNG.Connection.Protocol
{
string username = InterfaceControl.Info?.Username ?? "";
string password = InterfaceControl.Info?.Password ?? "";
string password = InterfaceControl.Info?.Password.ConvertToUnsecureString() ?? "";
string domain = InterfaceControl.Info?.Domain ?? "";
string UserViaAPI = InterfaceControl.Info?.UserViaAPI ?? "";
string privatekey = "";

View File

@@ -20,6 +20,7 @@ using System.Runtime.Versioning;
using FileDialog = Microsoft.Win32.FileDialog;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.StartPanel;
using System.DirectoryServices.ActiveDirectory;
using mRemoteNG.Security;
namespace mRemoteNG.Connection.Protocol.RDP
{
@@ -425,7 +426,7 @@ namespace mRemoteNG.Connection.Protocol.RDP
{
case RDGatewayUseConnectionCredentials.Yes:
_rdpClient.TransportSettings2.GatewayUsername = connectionInfo.Username;
_rdpClient.TransportSettings2.GatewayPassword = connectionInfo.Password;
_rdpClient.TransportSettings2.GatewayPassword = connectionInfo.Password.ConvertToUnsecureString();
_rdpClient.TransportSettings2.GatewayDomain = connectionInfo?.Domain;
break;
case RDGatewayUseConnectionCredentials.SmartCard:
@@ -536,10 +537,10 @@ namespace mRemoteNG.Connection.Protocol.RDP
}
string userName = connectionInfo?.Username ?? "";
string password = connectionInfo?.Password ?? "";
string domain = connectionInfo?.Domain ?? "";
string userViaApi = connectionInfo?.UserViaAPI ?? "";
string pkey = "";
string password = (connectionInfo?.Password?.ConvertToUnsecureString() ?? "");
// access secret server api if necessary
if (InterfaceControl.Info.ExternalCredentialProvider == ExternalCredentialProvider.DelineaSecretServer)

View File

@@ -7,6 +7,7 @@ using mRemoteNG.Tools;
using mRemoteNG.UI.Forms;
using mRemoteNG.Resources.Language;
using System.Runtime.Versioning;
using mRemoteNG.Security;
// ReSharper disable ArrangeAccessorOwnerBody
@@ -225,7 +226,7 @@ namespace mRemoteNG.Connection.Protocol.VNC
private string VNCEvent_Authenticate()
{
return _info.Password;
return _info.Password.ConvertToUnsecureString();
}
#endregion

View File

@@ -8,6 +8,7 @@ using mRemoteNG.Tree;
using mRemoteNG.Tree.Root;
using mRemoteNG.Resources.Language;
using System.Runtime.Versioning;
using System.Security;
namespace mRemoteNG.Connection
{
@@ -42,7 +43,7 @@ namespace mRemoteNG.Connection
[ReadOnly(true)] public override string Username { get; set; }
[ReadOnly(true), Browsable(false)] public override string Password { get; set; }
[ReadOnly(true), Browsable(false)] public override SecureString Password { get; set; }
[ReadOnly(true)] public override ProtocolType Protocol { get; set; }

View File

@@ -18,10 +18,10 @@ using System.Resources;
[assembly: AssemblyCulture("")]
// Version information
[assembly: AssemblyVersion("1.77.3.1839")]
[assembly: AssemblyFileVersion("1.77.3.1839")]
[assembly: AssemblyVersion("1.77.3.1852")]
[assembly: AssemblyFileVersion("1.77.3.1852")]
[assembly: NeutralResourcesLanguageAttribute("en-US")]
[assembly: AssemblyInformationalVersion("1.77.3 (Nightly Build 1839)")]
[assembly: AssemblyInformationalVersion("1.77.3 (Nightly Build 1852)")]
// Logging
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config")]

View File

@@ -4,6 +4,7 @@ using System.Runtime.Versioning;
using mRemoteNG.App;
using mRemoteNG.Connection;
using mRemoteNG.Properties;
using mRemoteNG.Security;
using mRemoteNG.Security.SymmetricEncryption;
using mRemoteNG.Tools.Cmdline;
@@ -186,7 +187,7 @@ namespace mRemoteNG.Tools
replacement = Properties.OptionsCredentialsPage.Default.DefaultUsername;
break;
case "password":
replacement = _connectionInfo.Password;
replacement = _connectionInfo.Password.ConvertToUnsecureString();
if (string.IsNullOrEmpty(replacement) && Properties.OptionsCredentialsPage.Default.EmptyCredentials == "custom")
replacement = new LegacyRijndaelCryptographyProvider().Decrypt(Convert.ToString(Properties.OptionsCredentialsPage.Default.DefaultPassword), Runtime.EncryptionKey);
break;

View File

@@ -12,6 +12,7 @@ using mRemoteNG.Tree;
using mRemoteNG.Tree.Root;
using mRemoteNG.Resources.Language;
using System.Runtime.Versioning;
using mRemoteNG.Security;
// ReSharper disable UnusedParameter.Local
@@ -832,7 +833,7 @@ namespace mRemoteNG.UI.Controls
Windows.Show(WindowType.SSHTransfer);
Windows.SshtransferForm.Hostname = _connectionTree.SelectedNode.Hostname;
Windows.SshtransferForm.Username = _connectionTree.SelectedNode.Username;
Windows.SshtransferForm.Password = _connectionTree.SelectedNode.Password;
Windows.SshtransferForm.Password = _connectionTree.SelectedNode.Password.ConvertToUnsecureString();
Windows.SshtransferForm.Port = Convert.ToString(_connectionTree.SelectedNode.Port);
}
catch (Exception ex)

View File

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -20,6 +20,7 @@ using mRemoteNG.UI.TaskDialog;
using WeifenLuo.WinFormsUI.Docking;
using mRemoteNG.Resources.Language;
using System.Runtime.Versioning;
using mRemoteNG.Security;
namespace mRemoteNG.UI.Window
{
@@ -469,7 +470,7 @@ namespace mRemoteNG.UI.Window
Windows.SshtransferForm.Hostname = connectionInfo.Hostname;
Windows.SshtransferForm.Username = connectionInfo.Username;
Windows.SshtransferForm.Password = connectionInfo.Password;
Windows.SshtransferForm.Password = connectionInfo.Password.ConvertToUnsecureString();
Windows.SshtransferForm.Port = Convert.ToString(connectionInfo.Port);
}
catch (Exception ex)

View File

@@ -19,7 +19,7 @@ public class CredentialHarvesterTests
private CredentialHarvester _credentialHarvester;
private ICryptographyProvider _cryptographyProvider;
private SecureString _key;
private SecureString _password = "mypass".ConvertToSecureString();
[SetUp]
public void Setup()
{
@@ -31,7 +31,7 @@ public class CredentialHarvesterTests
[Test]
public void HarvestsUsername()
{
var connection = new ConnectionInfo { Username = "myuser", Domain = "somedomain", Password = "mypass" };
var connection = new ConnectionInfo { Username = "myuser", Domain = "somedomain", Password = _password };
var xdoc = CreateTestData(connection);
var credentials = _credentialHarvester.Harvest(xdoc, _key);
Assert.That(credentials.Single().Username, Is.EqualTo(connection.Username));
@@ -40,7 +40,7 @@ public class CredentialHarvesterTests
[Test]
public void HarvestsDomain()
{
var connection = new ConnectionInfo { Username = "myuser", Domain = "somedomain", Password = "mypass" };
var connection = new ConnectionInfo { Username = "myuser", Domain = "somedomain", Password = _password };
var xdoc = CreateTestData(connection);
var credentials = _credentialHarvester.Harvest(xdoc, _key);
Assert.That(credentials.Single().Domain, Is.EqualTo(connection.Domain));
@@ -49,10 +49,10 @@ public class CredentialHarvesterTests
[Test]
public void HarvestsPassword()
{
var connection = new ConnectionInfo { Username = "myuser", Domain = "somedomain", Password = "mypass" };
var connection = new ConnectionInfo { Username = "myuser", Domain = "somedomain", Password = _password };
var xdoc = CreateTestData(connection);
var credentials = _credentialHarvester.Harvest(xdoc, _key);
Assert.That(credentials.Single().Password.ConvertToUnsecureString(), Is.EqualTo(connection.Password));
Assert.That(credentials.Single().Password.ConvertToUnsecureString(), Is.EqualTo(connection.Password.ConvertToUnsecureString()));
}
[Test]
@@ -91,7 +91,7 @@ public class CredentialHarvesterTests
[Test]
public void CredentialMapCorrectForSingleCredential()
{
var connection = new ConnectionInfo { Username = "myuser", Domain = "somedomain", Password = "mypass" };
var connection = new ConnectionInfo { Username = "myuser", Domain = "somedomain", Password = _password };
var connectionGuid = Guid.Parse(connection.ConstantID);
var xdoc = CreateTestData(connection);
_credentialHarvester.Harvest(xdoc, _key);

View File

@@ -73,7 +73,7 @@ namespace mRemoteNGTests.Config.Serializers.ConnectionSerializers.Csv
Icon = "SomeIcon",
Panel = "SomePanel",
Username = "SomeUsername",
Password = "SomePassword",
Password = "SomePassword".ConvertToSecureString(),
Domain = "SomeDomain",
Hostname = "SomeHostname",
PuttySession = "SomePuttySession",
@@ -168,6 +168,9 @@ namespace mRemoteNGTests.Config.Serializers.ConnectionSerializers.Csv
foreach (var property in properties)
{
if (property.Name == "Password")
continue;
testCases.Add(
new TestCaseData(property.Name)
.Returns(property.GetValue(testConnectionInfo)));

View File

@@ -113,7 +113,7 @@ public class CsvConnectionsSerializerMremotengFormatTests
Assert.That(csv, Does.Match(container.Name));
Assert.That(csv, Does.Match(container.Username));
Assert.That(csv, Does.Match(container.Domain));
Assert.That(csv, Does.Match(container.Password));
Assert.That(csv, Does.Match(container.Password?.ConvertToUnsecureString()));
Assert.That(csv, Does.Contain(TreeNodeType.Container.ToString()));
}
@@ -128,7 +128,7 @@ public class CsvConnectionsSerializerMremotengFormatTests
.First(s => s.Contains(serializationTarget.Name));
Assert.That(lineWithFolder3, Does.Contain(serializationTarget.Username));
Assert.That(lineWithFolder3, Does.Contain(serializationTarget.Domain));
Assert.That(lineWithFolder3, Does.Contain(serializationTarget.Password));
Assert.That(lineWithFolder3, Does.Contain(serializationTarget.Password?.ConvertToUnsecureString()));
}
private ConnectionInfo BuildConnectionInfo()
@@ -138,7 +138,7 @@ public class CsvConnectionsSerializerMremotengFormatTests
Name = ConnectionName,
Username = Username,
Domain = Domain,
Password = Password,
Password = Password?.ConvertToSecureString(),
Inheritance = { Colors = true }
};
}
@@ -150,7 +150,7 @@ public class CsvConnectionsSerializerMremotengFormatTests
Name = "MyFolder",
Username = "BlahBlah1",
Domain = "aklkskkksh8",
Password = "qweraslkdjf87"
Password = "qweraslkdjf87".ConvertToSecureString()
};
}
}

View File

@@ -3,6 +3,7 @@ using mRemoteNG.Config.Serializers.MiscSerializers;
using mRemoteNG.Connection;
using mRemoteNG.Connection.Protocol;
using mRemoteNG.Container;
using mRemoteNG.Security;
using mRemoteNGTests.Properties;
using NUnit.Framework;
@@ -99,7 +100,7 @@ public class PuttyConnectionManagerDeserializerTests
public void ConnectionPasswordImported()
{
var connection = GetSshConnection();
Assert.That(connection.Password, Is.EqualTo(ExpectedConnectionPassword));
Assert.That(connection.Password?.ConvertToUnsecureString(), Is.EqualTo(ExpectedConnectionPassword));
}
private ConnectionInfo GetSshConnection()

View File

@@ -4,6 +4,7 @@ using mRemoteNG.Connection.Protocol;
using mRemoteNG.Connection.Protocol.Http;
using mRemoteNG.Connection.Protocol.RDP;
using mRemoteNG.Connection.Protocol.VNC;
using mRemoteNG.Security;
using NUnit.Framework;
@@ -93,7 +94,7 @@ public class AbstractConnectionInfoDataTests
{
var wasCalled = false;
_testAbstractConnectionInfoData.PropertyChanged += (sender, args) => wasCalled = true;
_testAbstractConnectionInfoData.Password = "a";
_testAbstractConnectionInfoData.Password = "a".ConvertToSecureString();
Assert.That(wasCalled, Is.True);
}

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Reflection;
using mRemoteNG.Connection;
using mRemoteNGTests.TestHelpers;
@@ -51,6 +52,14 @@ namespace mRemoteNGTests.Connection
var valueInSource = property.GetValue(DefaultConnectionInfo.Instance)?.ToString();
var valueInDestination = saveTarget.GetType().GetProperty(property.Name)?.GetValue(saveTarget)?.ToString();
try
{
Assert.That(valueInDestination, Is.EqualTo(valueInSource));
}
catch (AssertionException)
{
Console.WriteLine($"Assertion Failed: Parameter {property.Name}");
}
Assert.That(valueInDestination, Is.EqualTo(valueInSource));
}

View File

@@ -115,6 +115,9 @@ namespace mRemoteNGTests.IntegrationTests
var sb = new StringBuilder();
foreach (var property in originalConnectionInfo.GetSerializableProperties())
{
if (property.Name == nameof(ConnectionInfo.Password))
continue;
var originalValue = property.GetValue(originalConnectionInfo);
var deserializedValue = property.GetValue(deserializedConnectionInfo);
if (originalValue.Equals(deserializedValue))
@@ -143,6 +146,9 @@ namespace mRemoteNGTests.IntegrationTests
var sb = new StringBuilder();
foreach (var property in originalConnectionInfo.Inheritance.GetProperties())
{
if (property.Name == nameof(originalConnectionInfo.Password))
continue;
var originalValue = property.GetValue(originalConnectionInfo.Inheritance);
var deserializedValue = property.GetValue(deserializedConnectionInfo.Inheritance);

View File

@@ -1,5 +1,6 @@
using mRemoteNG.Connection;
using mRemoteNG.Container;
using mRemoteNG.Security;
using mRemoteNG.Tree;
using mRemoteNG.Tree.Root;
@@ -22,8 +23,8 @@ namespace mRemoteNGTests.TestHelpers
{
var model = new ConnectionTreeModel();
var root = new RootNodeInfo(RootNodeType.Connection);
var folder1 = new ContainerInfo { Name = "folder1", Username = "user1", Domain = "domain1", Password = "password1" };
var folder2 = new ContainerInfo { Name = "folder2", Username = "user2", Domain = "domain2", Password = "password2" };
var folder1 = new ContainerInfo { Name = "folder1", Username = "user1", Domain = "domain1", Password = "password1".ConvertToSecureString() };
var folder2 = new ContainerInfo { Name = "folder2", Username = "user2", Domain = "domain2", Password = "password2".ConvertToSecureString() };
var folder3 = new ContainerInfo
{
Name = "folder3",
@@ -34,8 +35,8 @@ namespace mRemoteNGTests.TestHelpers
Password = true
}
};
var con1 = new ConnectionInfo { Name = "Con1", Username = "user1", Domain = "domain1", Password = "password1" };
var con2 = new ConnectionInfo { Name = "Con2", Username = "user2", Domain = "domain2", Password = "password2" };
var con1 = new ConnectionInfo { Name = "Con1", Username = "user1", Domain = "domain1", Password = "password1".ConvertToSecureString() };
var con2 = new ConnectionInfo { Name = "Con2", Username = "user2", Domain = "domain2", Password = "password2".ConvertToSecureString() };
var con3 = new ContainerInfo
{
Name = "con3",

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections;
using mRemoteNG.Connection;
using mRemoteNG.Security;
using mRemoteNG.Tools;
using NUnit.Framework;
@@ -28,7 +29,7 @@ namespace mRemoteNGTests.Tools
Hostname = TestString,
Port = Port,
Username = TestString,
Password = TestString,
Password = TestString.ConvertToSecureString(),
Domain = TestString,
Description = TestString,
MacAddress = TestString,