Compare commits

...

28 Commits

Author SHA1 Message Date
Dimitrij
9e70dce626 update PuTTY to v.0.75 2021-07-04 14:44:56 +01:00
David Sparer
52d1b9a270 Merge branch 'release/v1.76' 2019-04-12 09:14:26 -05:00
David Sparer
068f5942e7 updated changelog and bumped version to 1.76.20 2019-04-12 08:38:06 -05:00
David Sparer
703cefaf19 ensure rdcman import never sets properties to null. fixes #1401 2019-04-12 08:24:05 -05:00
Sean Kaim
3d32557177 Merge pull request #1390 from mRemoteNG/release/v1.76
Release/v1.76
2019-04-04 15:51:02 -04:00
Sean Kaim
ea1f72b8b7 bump version and changelog update 2019-04-04 15:44:34 -04:00
Sean Kaim
993b6759cc Update PuTTYNG.exe
Reference #1374
2019-04-04 15:41:55 -04:00
David Sparer
c0b07307f5 Merge branch 'release/v1.76' 2019-03-20 10:38:31 -05:00
David Sparer
15f23769d6 bumped version to v1.76.18 and updated changelog 2019-03-20 09:33:21 -05:00
Sean Kaim
2d175fd575 border fix for puttyng 0.70.0.1+ -- backported from develop 2019-03-20 10:21:56 -04:00
David Sparer
bdeb4b4dcc bumped version to v1.76.17 and updated changelog 2019-03-20 07:32:27 -05:00
David Sparer
bdfbb57504 updated puttyng to 0.71
fixes #1362
2019-03-20 07:29:13 -05:00
David Sparer
38d1c756f3 Merge branch 'release/v1.76' 2019-03-14 18:01:20 -05:00
David Sparer
6c89913bc6 updated changelog 2019-03-14 17:58:53 -05:00
David Sparer
efa72cb697 bumped version to 1.76.16 2019-03-14 17:58:43 -05:00
David Sparer
a31fec5fb9 encrypt correct db field
fixes #1347
2019-03-14 17:35:28 -05:00
David Sparer
ed81030976 bumped v1.76.15 release date 2019-03-09 11:21:21 -06:00
David Sparer
54322ca949 updated changelog 2019-03-08 10:41:57 -06:00
David Sparer
738b159e95 handle sql first-run case
fixes #1303
2019-03-08 10:31:39 -06:00
David Sparer
e8f2e4f50c bumped patch version 2019-03-04 11:45:07 -06:00
David Sparer
5cd201440e added tests for the disposable action class 2019-03-04 11:44:30 -06:00
David Sparer
5c6c76b898 one more parse bug fix 2019-03-04 11:30:34 -06:00
David Sparer
4847ce054b resolved several parsing bugs in the rdcman deserializer 2019-03-04 11:17:45 -06:00
David Sparer
ec42fe7d7d improved testability of the import class 2019-03-04 11:17:19 -06:00
David Sparer
07a20ed5ad batch saves when importing connection files
This reduces saves/backup overwrites when importing multiple files
2019-03-04 08:41:27 -06:00
Sean Kaim
08201b0f00 Port FIPS override back to 1.76
Fixes #222
2019-02-08 16:51:58 -05:00
David Sparer
8ab221e5a8 Merge branch 'release/v1.76' 2018-10-18 17:29:11 -05:00
David Sparer
d1a7a37909 Merge branch 'release/v1.76' 2018-10-07 18:42:03 -05:00
28 changed files with 790 additions and 363 deletions

View File

@@ -1,3 +1,57 @@
1.76.20 (2019-04-12):
Fixes:
------
#1401: Connections corrupted when importing RDC Manager files that are missing certain fields
1.76.19 (2019-04-04):
Fixes:
------
#1374: Vertical Scroll Bar missing in PuTTYNG after 0.70.0.1 & 0.71 updates
1.76.18 (2019-03-20):
Fixes:
------
#1365: PuTTY window not centered after 0.71 update
1.76.17 (2019-03-20):
Fixes:
------
#1362: Updated PuTTYNG to 0.71
1.76.16 (2019-03-14):
Fixes:
------
#1347: Remote Desktop Gateway username field encrypted instead of password
1.76.15 (2019-03-09):
Fixes:
------
#1303: Exception on first connection with new SQL server database
#1304: Resolved several issues with importing multiple RDP Manager v2.7 files
Features/Enhancements:
----------------------
Importing multiple files now only causes 1 save event, rather than 1 per file imported.
1.76.14 (2019-02-08):
Features/Enhancements:
----------------------
#222: Allow FIPS to be enabled
1.76.13 (2018-12-22):
Changes:

View File

@@ -0,0 +1,47 @@
using System.IO;
using mRemoteNG.App;
using mRemoteNG.Config.Putty;
using mRemoteNG.Connection;
using mRemoteNG.Container;
using mRemoteNGTests.Properties;
using mRemoteNGTests.TestHelpers;
using NUnit.Framework;
namespace mRemoteNGTests.App
{
public class ImportTests
{
[Test]
public void ErrorHandlerCalledWhenUnsupportedFileExtensionFound()
{
using (FileTestHelpers.DisposableTempFile(out var file, ".blah"))
{
var conService = new ConnectionsService(PuttySessionsManager.Instance);
var container = new ContainerInfo();
var exceptionOccurred = false;
Import.HeadlessFileImport(new []{file}, container, conService, s => exceptionOccurred = true);
Assert.That(exceptionOccurred);
}
}
[Test]
public void AnErrorInOneFileDoNotPreventOtherFilesFromProcessing()
{
using (FileTestHelpers.DisposableTempFile(out var badFile, ".blah"))
using (FileTestHelpers.DisposableTempFile(out var rdpFile, ".rdp"))
{
File.AppendAllText(rdpFile, Resources.test_remotedesktopconnection_rdp);
var conService = new ConnectionsService(PuttySessionsManager.Instance);
var container = new ContainerInfo();
var exceptionCount = 0;
Import.HeadlessFileImport(new[] { badFile, rdpFile }, container, conService, s => exceptionCount++);
Assert.That(exceptionCount, Is.EqualTo(1));
Assert.That(container.Children, Has.One.Items);
}
}
}
}

View File

@@ -1,20 +1,21 @@
using System.IO;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using mRemoteNG.Config.Serializers;
using mRemoteNG.Connection;
using mRemoteNG.Connection.Protocol;
using mRemoteNG.Connection.Protocol.RDP;
using mRemoteNG.Container;
using mRemoteNG.Tree;
using mRemoteNGTests.Properties;
using NUnit.Framework;
namespace mRemoteNGTests.Config.Serializers.MiscSerializers
{
public class RemoteDesktopConnectionManager27DeserializerTests
public class RemoteDesktopConnectionManager27DeserializerTests
{
private string _connectionFileContents;
private RemoteDesktopConnectionManagerDeserializer _deserializer;
private ConnectionTreeModel _connectionTreeModel;
private const string ExpectedName = "server1_displayname";
private const string ExpectedHostname = "server1";
private const string ExpectedDescription = "Comment text here";
@@ -44,265 +45,80 @@ namespace mRemoteNGTests.Config.Serializers.MiscSerializers
{
_connectionFileContents = Resources.test_rdcman_v2_7_schema3;
_deserializer = new RemoteDesktopConnectionManagerDeserializer();
_connectionTreeModel = _deserializer.Deserialize(_connectionFileContents);
}
[Test]
public void ConnectionTreeModelHasARootNode()
{
var numberOfRootNodes = _connectionTreeModel.RootNodes.Count;
var connectionTreeModel = _deserializer.Deserialize(_connectionFileContents);
var numberOfRootNodes = connectionTreeModel.RootNodes.Count;
Assert.That(numberOfRootNodes, Is.GreaterThan(0));
}
[Test]
public void RootNodeHasContents()
{
var rootNodeContents = _connectionTreeModel.RootNodes.First().Children;
var connectionTreeModel = _deserializer.Deserialize(_connectionFileContents);
var rootNodeContents = connectionTreeModel.RootNodes.First().Children;
Assert.That(rootNodeContents, Is.Not.Empty);
}
[Test]
public void AllSubRootFoldersImported()
{
var rootNode = _connectionTreeModel.RootNodes.First();
var connectionTreeModel = _deserializer.Deserialize(_connectionFileContents);
var rootNode = connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var rootNodeContents = importedRdcmanRootNode.Children.Count(node => node.Name == "Group1" || node.Name == "Group2");
Assert.That(rootNodeContents, Is.EqualTo(2));
}
[Test]
public void ConnectionDisplayNameImported()
[TestCaseSource(nameof(ExpectedPropertyValues))]
public void PropertiesWithValuesAreCorrectlyImported(Func<ConnectionInfo, object> propSelector, object expectedValue)
{
var rootNode = _connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
var connection = group1.Children.First();
Assert.That(connection.Name, Is.EqualTo(ExpectedName));
var connectionTreeModel = _deserializer.Deserialize(_connectionFileContents);
var connection = connectionTreeModel
.GetRecursiveChildList()
.OfType<ContainerInfo>()
.First(node => node.Name == "Group1")
.Children
.First();
Assert.That(propSelector(connection), Is.EqualTo(expectedValue));
}
[Test]
public void ConnectionHostnameImported()
[TestCaseSource(nameof(NullPropertyValues))]
public void PropertiesWithoutValuesAreIgnored(Func<ConnectionInfo, object> propSelector)
{
var rootNode = _connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
var connection = group1.Children.First();
Assert.That(connection.Hostname, Is.EqualTo(ExpectedHostname));
var connectionTreeModel = _deserializer.Deserialize(Resources.test_rdcman_v2_7_schema3_empty_values);
var importedConnection = connectionTreeModel
.GetRecursiveChildList()
.OfType<ContainerInfo>()
.First(node => node.Name == "Group1")
.Children
.First();
Assert.That(propSelector(importedConnection), Is.EqualTo(propSelector(new ConnectionInfo())));
}
[Test]
public void ConnectionDescriptionImported()
[TestCaseSource(nameof(NullPropertyValues))]
public void NonExistantPropertiesAreIgnored(Func<ConnectionInfo, object> propSelector)
{
var rootNode = _connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
var connection = group1.Children.First();
Assert.That(connection.Description, Is.EqualTo(ExpectedDescription));
var connectionTreeModel = _deserializer.Deserialize(Resources.test_rdcman_v2_7_schema3_null_values);
var importedConnection = connectionTreeModel
.GetRecursiveChildList()
.OfType<ContainerInfo>()
.First(node => node.Name == "Group1")
.Children
.First();
Assert.That(propSelector(importedConnection), Is.EqualTo(propSelector(new ConnectionInfo())));
}
[Test]
public void ConnectionUsernameImported()
{
var rootNode = _connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
var connection = group1.Children.First();
Assert.That(connection.Username, Is.EqualTo(ExpectedUsername));
}
[Test]
public void ConnectionDomainImported()
{
var rootNode = _connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
var connection = group1.Children.First();
Assert.That(connection.Domain, Is.EqualTo(ExpectedDomain));
}
// Since password is encrypted with a machine key, cant test decryption on another machine
//[Test]
//public void ConnectionPasswordImported()
//{
// var rootNode = _connectionTreeModel.RootNodes.First();
// var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
// var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
// var connection = group1.Children.First();
// Assert.That(connection.Password, Is.EqualTo(ExpectedPassword));
//}
[Test]
public void ConnectionProtocolSetToRdp()
{
var rootNode = _connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
var connection = group1.Children.First();
Assert.That(connection.Protocol, Is.EqualTo(ProtocolType.RDP));
}
[Test]
public void ConnectionUseConsoleSessionImported()
{
var rootNode = _connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
var connection = group1.Children.First();
Assert.That(connection.UseConsoleSession, Is.EqualTo(ExpectedUseConsoleSession));
}
[Test]
public void ConnectionPortImported()
{
var rootNode = _connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
var connection = group1.Children.First();
Assert.That(connection.Port, Is.EqualTo(ExpectedPort));
}
[Test]
public void ConnectionGatewayUsageMethodImported()
{
var rootNode = _connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
var connection = group1.Children.First();
Assert.That(connection.RDGatewayUsageMethod, Is.EqualTo(ExpectedGatewayUsageMethod));
}
[Test]
public void ConnectionGatewayHostnameImported()
{
var rootNode = _connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
var connection = group1.Children.First();
Assert.That(connection.RDGatewayHostname, Is.EqualTo(ExpectedGatewayHostname));
}
[Test]
public void ConnectionGatewayUsernameImported()
{
var rootNode = _connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
var connection = group1.Children.First();
Assert.That(connection.RDGatewayUsername, Is.EqualTo(ExpectedGatewayUsername));
}
// Since password is encrypted with a machine key, cant test decryption on another machine
//[Test]
//public void ConnectionGatewayPasswordImported()
//{
// var rootNode = _connectionTreeModel.RootNodes.First();
// var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
// var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
// var connection = group1.Children.First();
// Assert.That(connection.RDGatewayPassword, Is.EqualTo(ExpectedGatewayPassword));
//}
[Test]
public void ConnectionGatewayDomainImported()
{
var rootNode = _connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
var connection = group1.Children.First();
Assert.That(connection.RDGatewayDomain, Is.EqualTo(ExpectedGatewayDomain));
}
[Test]
public void ConnectionResolutionImported()
{
var rootNode = _connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
var connection = group1.Children.First();
Assert.That(connection.Resolution, Is.EqualTo(ExpectedRdpResolution));
}
[Test]
public void ConnectionColorDepthImported()
{
var rootNode = _connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
var connection = group1.Children.First();
Assert.That(connection.Colors, Is.EqualTo(ExpectedRdpColorDepth));
}
[Test]
public void ConnectionAudioRedirectionImported()
{
var rootNode = _connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
var connection = group1.Children.First();
Assert.That(connection.RedirectSound, Is.EqualTo(ExpectedAudioRedirection));
}
[Test]
public void ConnectionKeyRedirectionImported()
{
var rootNode = _connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
var connection = group1.Children.First();
Assert.That(connection.RedirectKeys, Is.EqualTo(ExpectedKeyRedirection));
}
[Test]
public void ConnectionDriveRedirectionImported()
{
var rootNode = _connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
var connection = group1.Children.First();
Assert.That(connection.RedirectDiskDrives, Is.EqualTo(ExpectedDriveRedirection));
}
[Test]
public void ConnectionPortRedirectionImported()
{
var rootNode = _connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
var connection = group1.Children.First();
Assert.That(connection.RedirectPorts, Is.EqualTo(ExpectedPortRedirection));
}
[Test]
public void ConnectionPrinterRedirectionImported()
{
var rootNode = _connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
var connection = group1.Children.First();
Assert.That(connection.RedirectPrinters, Is.EqualTo(ExpectedPrinterRedirection));
}
[Test]
public void ConnectionSmartcardRedirectionImported()
{
var rootNode = _connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
var connection = group1.Children.First();
Assert.That(connection.RedirectSmartCards, Is.EqualTo(ExpectedSmartcardRedirection));
}
[Test]
public void ConnectionauthenticationLevelImported()
{
var rootNode = _connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
var connection = group1.Children.First();
Assert.That(connection.RDPAuthenticationLevel, Is.EqualTo(ExpectedAuthLevel));
}
[Test]
[Test]
public void ExceptionThrownOnBadSchemaVersion()
{
var badFileContents = Resources.test_rdcman_v2_2_badschemaversion;
@@ -322,5 +138,61 @@ namespace mRemoteNGTests.Config.Serializers.MiscSerializers
var badFileContents = Resources.test_rdcman_noversion;
Assert.That(() => _deserializer.Deserialize(badFileContents), Throws.TypeOf<FileFormatException>());
}
private static IEnumerable<TestCaseData> ExpectedPropertyValues()
{
return new[]
{
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Name), ExpectedName).SetName(nameof(ConnectionInfo.Name)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Hostname), ExpectedHostname).SetName(nameof(ConnectionInfo.Hostname)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Description), ExpectedDescription).SetName(nameof(ConnectionInfo.Description)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Username), ExpectedUsername).SetName(nameof(ConnectionInfo.Username)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Domain), ExpectedDomain).SetName(nameof(ConnectionInfo.Domain)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Protocol), ProtocolType.RDP).SetName(nameof(ConnectionInfo.Protocol)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.UseConsoleSession), ExpectedUseConsoleSession).SetName(nameof(ConnectionInfo.UseConsoleSession)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Port), ExpectedPort).SetName(nameof(ConnectionInfo.Port)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RDGatewayUsageMethod), ExpectedGatewayUsageMethod).SetName(nameof(ConnectionInfo.RDGatewayUsageMethod)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RDGatewayHostname), ExpectedGatewayHostname).SetName(nameof(ConnectionInfo.RDGatewayHostname)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RDGatewayUsername), ExpectedGatewayUsername).SetName(nameof(ConnectionInfo.RDGatewayUsername)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RDGatewayDomain), ExpectedGatewayDomain).SetName(nameof(ConnectionInfo.RDGatewayDomain)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Resolution), ExpectedRdpResolution).SetName(nameof(ConnectionInfo.Resolution)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Colors), ExpectedRdpColorDepth).SetName(nameof(ConnectionInfo.Colors)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RedirectSound), ExpectedAudioRedirection).SetName(nameof(ConnectionInfo.RedirectSound)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RedirectKeys), ExpectedKeyRedirection).SetName(nameof(ConnectionInfo.RedirectKeys)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RDPAuthenticationLevel), ExpectedAuthLevel).SetName(nameof(ConnectionInfo.RDPAuthenticationLevel)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RedirectSmartCards), ExpectedSmartcardRedirection).SetName(nameof(ConnectionInfo.RedirectSmartCards)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RedirectPrinters), ExpectedPrinterRedirection).SetName(nameof(ConnectionInfo.RedirectPrinters)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RedirectPorts), ExpectedPortRedirection).SetName(nameof(ConnectionInfo.RedirectPorts)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RedirectDiskDrives), ExpectedDriveRedirection).SetName(nameof(ConnectionInfo.RedirectDiskDrives)),
};
}
private static IEnumerable<TestCaseData> NullPropertyValues()
{
return new[]
{
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Name)).SetName(nameof(ConnectionInfo.Name)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Hostname)).SetName(nameof(ConnectionInfo.Hostname)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Description)).SetName(nameof(ConnectionInfo.Description)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Username)).SetName(nameof(ConnectionInfo.Username)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Domain)).SetName(nameof(ConnectionInfo.Domain)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Protocol)).SetName(nameof(ConnectionInfo.Protocol)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.UseConsoleSession)).SetName(nameof(ConnectionInfo.UseConsoleSession)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Port)).SetName(nameof(ConnectionInfo.Port)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RDGatewayUsageMethod)).SetName(nameof(ConnectionInfo.RDGatewayUsageMethod)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RDGatewayHostname)).SetName(nameof(ConnectionInfo.RDGatewayHostname)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RDGatewayUsername)).SetName(nameof(ConnectionInfo.RDGatewayUsername)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RDGatewayDomain)).SetName(nameof(ConnectionInfo.RDGatewayDomain)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Resolution)).SetName(nameof(ConnectionInfo.Resolution)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Colors)).SetName(nameof(ConnectionInfo.Colors)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RedirectSound)).SetName(nameof(ConnectionInfo.RedirectSound)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RedirectKeys)).SetName(nameof(ConnectionInfo.RedirectKeys)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RDPAuthenticationLevel)).SetName(nameof(ConnectionInfo.RDPAuthenticationLevel)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RedirectSmartCards)).SetName(nameof(ConnectionInfo.RedirectSmartCards)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RedirectPrinters)).SetName(nameof(ConnectionInfo.RedirectPrinters)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RedirectPorts)).SetName(nameof(ConnectionInfo.RedirectPorts)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RedirectDiskDrives)).SetName(nameof(ConnectionInfo.RedirectDiskDrives)),
};
}
}
}

View File

@@ -298,6 +298,58 @@ namespace mRemoteNGTests.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
///&lt;RDCMan programVersion=&quot;2.7&quot; schemaVersion=&quot;3&quot;&gt;
/// &lt;file&gt;
/// &lt;credentialsProfiles /&gt;
/// &lt;properties&gt;
/// &lt;expanded&gt;True&lt;/expanded&gt;
/// &lt;name&gt;test_RDCMan_connections&lt;/name&gt;
/// &lt;/properties&gt;
/// &lt;smartGroup&gt;
/// &lt;properties&gt;
/// &lt;expanded&gt;False&lt;/expanded&gt;
/// &lt;name&gt;AllServers&lt;/name&gt;
/// &lt;/properties&gt;
/// &lt;ruleGroup operator=&quot;All&quot;&gt;
/// &lt;rule&gt;
/// &lt;property&gt;DisplayName&lt;/property&gt;
/// &lt;operator&gt;Matches&lt;/operator&gt;
/// [rest of string was truncated]&quot;;.
/// </summary>
internal static string test_rdcman_v2_7_schema3_empty_values {
get {
return ResourceManager.GetString("test_rdcman_v2_7_schema3_empty_values", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
///&lt;RDCMan programVersion=&quot;2.7&quot; schemaVersion=&quot;3&quot;&gt;
/// &lt;file&gt;
/// &lt;credentialsProfiles /&gt;
/// &lt;properties&gt;
/// &lt;expanded&gt;True&lt;/expanded&gt;
/// &lt;name&gt;test_RDCMan_connections&lt;/name&gt;
/// &lt;/properties&gt;
/// &lt;smartGroup&gt;
/// &lt;properties&gt;
/// &lt;expanded&gt;False&lt;/expanded&gt;
/// &lt;name&gt;AllServers&lt;/name&gt;
/// &lt;/properties&gt;
/// &lt;ruleGroup operator=&quot;All&quot;&gt;
/// &lt;rule&gt;
/// &lt;property&gt;DisplayName&lt;/property&gt;
/// &lt;operator&gt;Matches&lt;/operator&gt;
/// [rest of string was truncated]&quot;;.
/// </summary>
internal static string test_rdcman_v2_7_schema3_null_values {
get {
return ResourceManager.GetString("test_rdcman_v2_7_schema3_null_values", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to screen mode id:i:1
///use multimon:i:0

View File

@@ -172,6 +172,12 @@
<data name="test_rdcman_v2_7_schema3" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\test_RDCMan_v2_7_schema3.rdg;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
</data>
<data name="test_rdcman_v2_7_schema3_empty_values" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\test_rdcman_v2_7_schema3_empty_values.rdg;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
</data>
<data name="test_rdcman_v2_7_schema3_null_values" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\test_rdcman_v2_7_schema3_null_values.rdg;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
</data>
<data name="test_remotedesktopconnection_rdp" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\test_remotedesktopconnection.rdp;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16</value>
</data>

View File

@@ -0,0 +1,95 @@
<?xml version="1.0" encoding="utf-8"?>
<RDCMan programVersion="2.7" schemaVersion="3">
<file>
<credentialsProfiles />
<properties>
<expanded>True</expanded>
<name>test_RDCMan_connections</name>
</properties>
<smartGroup>
<properties>
<expanded>False</expanded>
<name>AllServers</name>
</properties>
<ruleGroup operator="All">
<rule>
<property>DisplayName</property>
<operator>Matches</operator>
<value>server</value>
</rule>
</ruleGroup>
</smartGroup>
<group>
<properties>
<expanded>True</expanded>
<name>Group1</name>
</properties>
<server>
<properties>
<displayName></displayName>
<name></name>
<comment></comment>
</properties>
<logonCredentials inherit="None">
<profileName scope="Local"></profileName>
<userName></userName>
<password></password>
<domain></domain>
</logonCredentials>
<connectionSettings inherit="None">
<connectToConsole></connectToConsole>
<startProgram />
<workingDir />
<port></port>
<loadBalanceInfo />
</connectionSettings>
<gatewaySettings inherit="None">
<enabled></enabled>
<hostName></hostName>
<logonMethod></logonMethod>
<localBypass></localBypass>
<credSharing></credSharing>
<profileName scope="Local"></profileName>
<userName></userName>
<password />
<domain></domain>
</gatewaySettings>
<remoteDesktop inherit="None">
<sameSizeAsClientArea></sameSizeAsClientArea>
<fullScreen></fullScreen>
<colorDepth></colorDepth>
</remoteDesktop>
<localResources inherit="None">
<audioRedirection></audioRedirection>
<audioRedirectionQuality></audioRedirectionQuality>
<audioCaptureRedirection></audioCaptureRedirection>
<keyboardHook></keyboardHook>
<redirectClipboard></redirectClipboard>
<redirectDrives></redirectDrives>
<redirectDrivesList>
<item></item>
<item></item>
<item></item>
<item></item>
<item></item>
</redirectDrivesList>
<redirectPrinters></redirectPrinters>
<redirectPorts></redirectPorts>
<redirectSmartCards></redirectSmartCards>
<redirectPnpDevices></redirectPnpDevices>
</localResources>
<displaySettings inherit="None">
<thumbnailScale></thumbnailScale>
<smartSizeDockedWindows></smartSizeDockedWindows>
<smartSizeUndockedWindows></smartSizeUndockedWindows>
</displaySettings>
<securitySettings inherit="None">
<authentication></authentication>
</securitySettings>
</server>
</group>
</file>
<connected />
<favorites />
<recentlyUsed />
</RDCMan>

View File

@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<RDCMan programVersion="2.7" schemaVersion="3">
<file>
<credentialsProfiles />
<properties>
<expanded>True</expanded>
<name>test_RDCMan_connections</name>
</properties>
<smartGroup>
<properties>
<expanded>False</expanded>
<name>AllServers</name>
</properties>
<ruleGroup operator="All">
<rule>
<property>DisplayName</property>
<operator>Matches</operator>
<value>server</value>
</rule>
</ruleGroup>
</smartGroup>
<group>
<properties>
<expanded>True</expanded>
<name>Group1</name>
</properties>
<server>
<properties>
</properties>
<logonCredentials inherit="None">
</logonCredentials>
<connectionSettings inherit="None">
</connectionSettings>
<gatewaySettings inherit="None">
</gatewaySettings>
<remoteDesktop inherit="None">
</remoteDesktop>
<localResources inherit="None">
</localResources>
<displaySettings inherit="None">
</displaySettings>
<securitySettings inherit="None">
</securitySettings>
</server>
</group>
</file>
<connected />
<favorites />
<recentlyUsed />
</RDCMan>

View File

@@ -1,4 +1,5 @@
using System.IO;
using mRemoteNG.Tools;
namespace mRemoteNGTests.TestHelpers
{
@@ -18,9 +19,17 @@ namespace mRemoteNGTests.TestHelpers
File.Delete(file);
}
public static string NewTempFilePath()
public static void DeleteDirectory(string directory)
{
if (Directory.Exists(directory))
Directory.Delete(directory, true);
}
public static string NewTempFilePath(string extension = "")
{
var newPath = Path.Combine(GetTestSpecificTempDirectory(), Path.GetRandomFileName());
if (!string.IsNullOrWhiteSpace(extension))
newPath = newPath + extension;
var folderPath = Path.GetDirectoryName(newPath);
if (!Directory.Exists(folderPath))
Directory.CreateDirectory(folderPath);
@@ -35,5 +44,15 @@ namespace mRemoteNGTests.TestHelpers
{
return Path.Combine(Path.GetTempPath(), "mRemoteNGTests", Path.GetRandomFileName());
}
public static DisposableAction DisposableTempFile(out string filePath, string extension = "")
{
var file = NewTempFilePath(extension);
filePath = file;
File.AppendAllText(file, "");
return new DisposableAction(
() => {},
() => DeleteDirectory(Path.GetDirectoryName(file)));
}
}
}

View File

@@ -0,0 +1,42 @@
using mRemoteNG.Tools;
using NUnit.Framework;
namespace mRemoteNGTests.Tools
{
public class DisposableActionTests
{
[Test]
public void InitializerActionRunsWhenObjectIsCreated()
{
var initializerRan = false;
new DisposableAction(() => initializerRan = true, () => { });
Assert.That(initializerRan);
}
[Test]
public void DisposalActionRunsWhenDisposeIsCalled()
{
var disposeActionRan = false;
var action = new DisposableAction(() => {}, () => disposeActionRan = true);
Assert.That(disposeActionRan, Is.False);
action.Dispose();
Assert.That(disposeActionRan, Is.True);
}
[Test]
public void DisposeActionOnlyExecutedOnceWhenCallingDisposeMultipleTimes()
{
var invokeCount = 0;
var action = new DisposableAction(() => { }, () => invokeCount++);
action.Dispose();
action.Dispose();
action.Dispose();
action.Dispose();
action.Dispose();
Assert.That(invokeCount, Is.EqualTo(1));
}
}
}

View File

@@ -108,6 +108,7 @@
</Otherwise>
</Choose>
<ItemGroup>
<Compile Include="App\ImportTests.cs" />
<Compile Include="App\UpdaterTests.cs" />
<Compile Include="BinaryFileTests.cs" />
<Compile Include="Config\Connections\Multiuser\ConnectionsUpdateAvailableEventArgsTests.cs" />
@@ -175,6 +176,7 @@
<Compile Include="Security\XmlCryptoProviderBuilderTests.cs" />
<Compile Include="TestHelpers\FileTestHelpers.cs" />
<Compile Include="TestHelpers\SerializableConnectionInfoAllPropertiesOfType.cs" />
<Compile Include="Tools\DisposableActionTests.cs" />
<Compile Include="Tools\ExternalToolsArgumentParserTests.cs" />
<Compile Include="Tools\FullyObservableCollectionTests.cs" />
<Compile Include="Tools\OptionalTests.cs" />
@@ -265,6 +267,8 @@
<None Include="Resources\test_rdcman_v2_2_badschemaversion.rdg" />
<None Include="Resources\test_rdcman_v2_2_schema1.rdg" />
<None Include="Resources\test_RDCMan_v2_7_schema3.rdg" />
<None Include="Resources\test_rdcman_v2_7_schema3_empty_values.rdg" />
<None Include="Resources\test_rdcman_v2_7_schema3_null_values.rdg" />
<None Include="Resources\test_remotedesktopconnection.rdp" />
</ItemGroup>
<ItemGroup>

View File

@@ -19,17 +19,29 @@ namespace mRemoteNG.App
private static void CheckFipsPolicy(MessageCollector messageCollector)
{
if (Settings.Default.OverrideFIPSCheck)
{
messageCollector.AddMessage(MessageClass.InformationMsg, "OverrideFIPSCheck is set. Will skip check...", true);
return;
}
messageCollector.AddMessage(MessageClass.InformationMsg, "Checking FIPS Policy...", true);
if (!FipsPolicyEnabledForServer2003() && !FipsPolicyEnabledForServer2008AndNewer()) return;
var errorText = string.Format(Language.strErrorFipsPolicyIncompatible, GeneralAppInfo.ProductName, GeneralAppInfo.ProductName);
var errorText = string.Format(Language.strErrorFipsPolicyIncompatible, GeneralAppInfo.ProductName);
messageCollector.AddMessage(MessageClass.ErrorMsg, errorText, true);
MessageBox.Show(FrmMain.Default, errorText, GeneralAppInfo.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
var CrashOverride = MessageBox.Show(FrmMain.Default, "TEST BUILD -- OK to test mRemoteNG with FIPS Enabled.\nCancel to Exit.", GeneralAppInfo.ProductName, MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation);
if (CrashOverride == DialogResult.OK)
var ShouldIStayOrShouldIGo = CTaskDialog.MessageBox(Application.ProductName, Language.strCompatibilityProblemDetected, errorText, "", "", Language.strCheckboxDoNotShowThisMessageAgain, ETaskDialogButtons.OkCancel, ESysIcons.Warning, ESysIcons.Warning);
if (CTaskDialog.VerificationChecked && ShouldIStayOrShouldIGo == DialogResult.OK)
{
messageCollector.AddMessage(MessageClass.ErrorMsg, "User requests that FIPS check be overridden", true);
Settings.Default.OverrideFIPSCheck = true;
Settings.Default.Save();
return;
}
Environment.Exit(1);
if (ShouldIStayOrShouldIGo == DialogResult.Cancel)
Environment.Exit(1);
}
private static bool FipsPolicyEnabledForServer2003()

View File

@@ -3,13 +3,14 @@ using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;
using mRemoteNG.Config.Import;
using mRemoteNG.Connection;
using mRemoteNG.Connection.Protocol;
using mRemoteNG.Container;
using mRemoteNG.Tools;
namespace mRemoteNG.App
{
public static class Import
public static class Import
{
public static void ImportFromFile(ContainerInfo importDestinationContainer)
{
@@ -35,22 +36,12 @@ namespace mRemoteNG.App
if (openFileDialog.ShowDialog() != DialogResult.OK)
return;
foreach (var fileName in openFileDialog.FileNames)
{
try
{
var importer = BuildConnectionImporterFromFileExtension(fileName);
importer.Import(fileName, importDestinationContainer);
}
catch (Exception ex)
{
MessageBox.Show(string.Format(Language.strImportFileFailedContent, fileName), Language.strImportFileFailedMainInstruction,
MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);
Runtime.MessageCollector.AddExceptionMessage("Unable to import file.", ex);
}
}
Runtime.ConnectionsService.SaveConnectionsAsync();
HeadlessFileImport(
openFileDialog.FileNames,
importDestinationContainer,
Runtime.ConnectionsService,
fileName => MessageBox.Show(string.Format(Language.strImportFileFailedContent, fileName), Language.strImportFileFailedMainInstruction,
MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1));
}
}
catch (Exception ex)
@@ -59,12 +50,38 @@ namespace mRemoteNG.App
}
}
public static void HeadlessFileImport(
IEnumerable<string> filePaths,
ContainerInfo importDestinationContainer,
ConnectionsService connectionsService,
Action<string> exceptionAction = null)
{
using (connectionsService.BatchedSavingContext())
{
foreach (var fileName in filePaths)
{
try
{
var importer = BuildConnectionImporterFromFileExtension(fileName);
importer.Import(fileName, importDestinationContainer);
}
catch (Exception ex)
{
exceptionAction?.Invoke(fileName);
Runtime.MessageCollector.AddExceptionMessage($"Error occurred while importing file '{fileName}'.", ex);
}
}
}
}
public static void ImportFromActiveDirectory(string ldapPath, ContainerInfo importDestinationContainer, bool importSubOu)
{
try
{
ActiveDirectoryImporter.Import(ldapPath, importDestinationContainer, importSubOu);
Runtime.ConnectionsService.SaveConnectionsAsync();
using (Runtime.ConnectionsService.BatchedSavingContext())
{
ActiveDirectoryImporter.Import(ldapPath, importDestinationContainer, importSubOu);
}
}
catch (Exception ex)
{
@@ -76,9 +93,11 @@ namespace mRemoteNG.App
{
try
{
var importer = new PortScanImporter(protocol);
importer.Import(hosts, importDestinationContainer);
Runtime.ConnectionsService.SaveConnectionsAsync();
using (Runtime.ConnectionsService.BatchedSavingContext())
{
var importer = new PortScanImporter(protocol);
importer.Import(hosts, importDestinationContainer);
}
}
catch (Exception ex)
{

View File

@@ -1,23 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security;
using mRemoteNG.Config.DatabaseConnectors;
using mRemoteNG.Config.DataProviders;
using mRemoteNG.Config.Serializers;
using mRemoteNG.Config.Serializers.MsSql;
using mRemoteNG.Config.Serializers.Versioning;
using mRemoteNG.Container;
using mRemoteNG.Tools;
using mRemoteNG.Tree;
using mRemoteNG.Tree.Root;
using System.Collections.Generic;
using System.Linq;
using System.Security;
using mRemoteNG.Security;
using mRemoteNG.Security.Authentication;
using mRemoteNG.Security.SymmetricEncryption;
using mRemoteNG.Tools;
using mRemoteNG.Tree;
using mRemoteNG.Tree.Root;
namespace mRemoteNG.Config.Connections
{
public class SqlConnectionsLoader : IConnectionsLoader
public class SqlConnectionsLoader : IConnectionsLoader
{
private readonly IDeserializer<string, IEnumerable<LocalConnectionPropertiesModel>> _localConnectionPropertiesDeserializer;
private readonly IDataProvider<string> _dataProvider;
@@ -41,7 +41,8 @@ namespace mRemoteNG.Config.Connections
var databaseVersionVerifier = new SqlDatabaseVersionVerifier(connector);
var cryptoProvider = new LegacyRijndaelCryptographyProvider();
var metaData = metaDataRetriever.GetDatabaseMetaData(connector);
var metaData = metaDataRetriever.GetDatabaseMetaData(connector) ??
HandleFirstRun(metaDataRetriever, connector);
var decryptionKey = GetDecryptionKey(metaData);
if (!decryptionKey.Any())
@@ -85,5 +86,11 @@ namespace mRemoteNG.Config.Connections
container.IsExpanded = x.LocalProperties.Expanded;
});
}
private SqlConnectionListMetaData HandleFirstRun(SqlDatabaseMetaDataRetriever metaDataRetriever, SqlDatabaseConnector connector)
{
metaDataRetriever.WriteDatabaseMetaData(new RootNodeInfo(RootNodeType.Connection), connector);
return metaDataRetriever.GetDatabaseMetaData(connector);
}
}
}

View File

@@ -1,10 +1,16 @@
using mRemoteNG.App;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Globalization;
using System.Linq;
using mRemoteNG.App;
using mRemoteNG.App.Info;
using mRemoteNG.Config.DatabaseConnectors;
using mRemoteNG.Config.DataProviders;
using mRemoteNG.Config.Serializers;
using mRemoteNG.Config.Serializers.MsSql;
using mRemoteNG.Config.Serializers.Versioning;
using mRemoteNG.Connection;
using mRemoteNG.Container;
using mRemoteNG.Messages;
using mRemoteNG.Security;
@@ -12,19 +18,11 @@ using mRemoteNG.Security.SymmetricEncryption;
using mRemoteNG.Tools;
using mRemoteNG.Tree;
using mRemoteNG.Tree.Root;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Globalization;
using System.Linq;
using System.Security;
using mRemoteNG.Connection;
namespace mRemoteNG.Config.Connections
{
public class SqlConnectionsSaver : ISaver<ConnectionTreeModel>
public class SqlConnectionsSaver : ISaver<ConnectionTreeModel>
{
private SecureString _password = Runtime.EncryptionKey;
private readonly SaveFilter _saveFilter;
private readonly ISerializer<IEnumerable<LocalConnectionPropertiesModel>, string> _localPropertiesSerializer;
private readonly IDataProvider<string> _dataProvider;
@@ -73,7 +71,7 @@ namespace mRemoteNG.Config.Connections
return;
}
UpdateRootNodeTable(rootTreeNode, sqlConnector);
metaDataRetriever.WriteDatabaseMetaData(rootTreeNode, sqlConnector);
UpdateConnectionsTable(rootTreeNode, sqlConnector);
UpdateUpdatesTable(sqlConnector);
}
@@ -117,17 +115,17 @@ namespace mRemoteNG.Config.Connections
{
if (rootTreeNode.Password)
{
_password = rootTreeNode.PasswordString.ConvertToSecureString();
strProtected = cryptographyProvider.Encrypt("ThisIsProtected", _password);
var password = rootTreeNode.PasswordString.ConvertToSecureString();
strProtected = cryptographyProvider.Encrypt("ThisIsProtected", password);
}
else
{
strProtected = cryptographyProvider.Encrypt("ThisIsNotProtected", _password);
strProtected = cryptographyProvider.Encrypt("ThisIsNotProtected", Runtime.EncryptionKey);
}
}
else
{
strProtected = cryptographyProvider.Encrypt("ThisIsNotProtected", _password);
strProtected = cryptographyProvider.Encrypt("ThisIsNotProtected", Runtime.EncryptionKey);
}
var sqlQuery = new SqlCommand("DELETE FROM tblRoot", sqlDatabaseConnector.SqlConnection);

View File

@@ -266,8 +266,8 @@ namespace mRemoteNG.Config.Serializers.MsSql
dataRow["RDGatewayUsageMethod"] = connectionInfo.RDGatewayUsageMethod;
dataRow["RDGatewayHostname"] = connectionInfo.RDGatewayHostname;
dataRow["RDGatewayUseConnectionCredentials"] = connectionInfo.RDGatewayUseConnectionCredentials;
dataRow["RDGatewayUsername"] = _cryptographyProvider.Encrypt(connectionInfo.RDGatewayUsername, _encryptionKey);
dataRow["RDGatewayPassword"] = connectionInfo.RDGatewayPassword;
dataRow["RDGatewayUsername"] = connectionInfo.RDGatewayUsername;
dataRow["RDGatewayPassword"] = _cryptographyProvider.Encrypt(connectionInfo.RDGatewayPassword, _encryptionKey);
dataRow["RDGatewayDomain"] = connectionInfo.RDGatewayDomain;
if (_saveFilter.SaveInheritance)
{

View File

@@ -2,12 +2,17 @@
using System.Data.SqlClient;
using System.Globalization;
using mRemoteNG.App;
using mRemoteNG.App.Info;
using mRemoteNG.Config.DatabaseConnectors;
using mRemoteNG.Messages;
using mRemoteNG.Security;
using mRemoteNG.Security.SymmetricEncryption;
using mRemoteNG.Tools;
using mRemoteNG.Tree.Root;
namespace mRemoteNG.Config.Serializers.MsSql
{
public class SqlDatabaseMetaDataRetriever
public class SqlDatabaseMetaDataRetriever
{
public SqlConnectionListMetaData GetDatabaseMetaData(SqlDatabaseConnector sqlDatabaseConnector)
{
@@ -44,5 +49,45 @@ namespace mRemoteNG.Config.Serializers.MsSql
}
return metaData;
}
public void WriteDatabaseMetaData(RootNodeInfo rootTreeNode, SqlDatabaseConnector sqlDatabaseConnector)
{
var cryptographyProvider = new LegacyRijndaelCryptographyProvider();
string strProtected;
if (rootTreeNode != null)
{
if (rootTreeNode.Password)
{
var password = rootTreeNode.PasswordString.ConvertToSecureString();
strProtected = cryptographyProvider.Encrypt("ThisIsProtected", password);
}
else
{
strProtected = cryptographyProvider.Encrypt("ThisIsNotProtected", Runtime.EncryptionKey);
}
}
else
{
strProtected = cryptographyProvider.Encrypt("ThisIsNotProtected", Runtime.EncryptionKey);
}
var sqlQuery = new SqlCommand("DELETE FROM tblRoot", sqlDatabaseConnector.SqlConnection);
sqlQuery.ExecuteNonQuery();
if (rootTreeNode != null)
{
sqlQuery =
new SqlCommand(
"INSERT INTO tblRoot (Name, Export, Protected, ConfVersion) VALUES(\'" +
MiscTools.PrepareValueForDB(rootTreeNode.Name) + "\', 0, \'" + strProtected + "\'," +
ConnectionsFileInfo.ConnectionFileVersion.ToString(CultureInfo.InvariantCulture) + ")",
sqlDatabaseConnector.SqlConnection);
sqlQuery.ExecuteNonQuery();
}
else
{
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, $"UpdateRootNodeTable: rootTreeNode was null. Could not insert!");
}
}
}
}

View File

@@ -13,7 +13,7 @@ using mRemoteNG.Tree.Root;
namespace mRemoteNG.Config.Serializers
{
public class RemoteDesktopConnectionManagerDeserializer : IDeserializer<string, ConnectionTreeModel>
public class RemoteDesktopConnectionManagerDeserializer : IDeserializer<string, ConnectionTreeModel>
{
private static int _schemaVersion; /* 1 = RDCMan v2.2
3 = RDCMan v2.7 */
@@ -40,11 +40,15 @@ namespace mRemoteNG.Config.Serializers
private static void VerifySchemaVersion(XmlNode rdcManNode)
{
_schemaVersion = Convert.ToInt32(rdcManNode?.Attributes?["schemaVersion"].Value);
if (_schemaVersion != 1 && _schemaVersion != 3)
if (!int.TryParse(rdcManNode?.Attributes?["schemaVersion"]?.Value, out var version))
throw new FileFormatException("Could not find schema version attribute.");
if (version != 1 && version != 3)
{
throw (new FileFormatException($"Unsupported schema version ({_schemaVersion})."));
throw new FileFormatException($"Unsupported schema version ({version}).");
}
_schemaVersion = version;
}
private static void VerifyFileVersion(XmlNode rdcManNode)
@@ -114,7 +118,8 @@ namespace mRemoteNG.Config.Serializers
containerPropertiesNode = containerPropertiesNode.SelectSingleNode("./properties");
}
newContainer.Name = containerPropertiesNode?.SelectSingleNode("./name")?.InnerText ?? Language.strNewFolder;
newContainer.IsExpanded = bool.Parse(containerPropertiesNode?.SelectSingleNode("./expanded")?.InnerText ?? "false");
if (bool.TryParse(containerPropertiesNode?.SelectSingleNode("./expanded")?.InnerText, out var expanded))
newContainer.IsExpanded = expanded;
parentContainer.AddChild(newContainer);
return newContainer;
}
@@ -129,17 +134,25 @@ namespace mRemoteNG.Config.Serializers
{
var connectionInfo = new ConnectionInfo {Protocol = ProtocolType.RDP};
var propertiesNode = xmlNode.SelectSingleNode("./properties");
if (_schemaVersion == 1) propertiesNode = xmlNode; // Version 2.2 defines the container name at the root instead
if (_schemaVersion == 1)
propertiesNode = xmlNode; // Version 2.2 defines the container name at the root instead
connectionInfo.Hostname = propertiesNode?.SelectSingleNode("./name")?.InnerText ?? "";
connectionInfo.Name = propertiesNode?.SelectSingleNode("./displayName")?.InnerText ?? connectionInfo.Hostname;
var connectionDisplayName = propertiesNode?.SelectSingleNode("./displayName")?.InnerText;
connectionInfo.Name = !string.IsNullOrWhiteSpace(connectionDisplayName)
? connectionDisplayName
: string.IsNullOrWhiteSpace(connectionInfo.Hostname)
? connectionInfo.Name
: connectionInfo.Hostname;
connectionInfo.Description = propertiesNode?.SelectSingleNode("./comment")?.InnerText ?? string.Empty;
var logonCredentialsNode = xmlNode.SelectSingleNode("./logonCredentials");
if (logonCredentialsNode?.Attributes?["inherit"]?.Value == "None")
{
connectionInfo.Username = logonCredentialsNode.SelectSingleNode("userName")?.InnerText;
connectionInfo.Username = logonCredentialsNode.SelectSingleNode("userName")?.InnerText ?? string.Empty;
var passwordNode = logonCredentialsNode.SelectSingleNode("./password");
if (_schemaVersion == 1) // Version 2.2 allows clear text passwords
@@ -153,7 +166,7 @@ namespace mRemoteNG.Config.Serializers
connectionInfo.Password = DecryptRdcManPassword(passwordNode?.InnerText);
}
connectionInfo.Domain = logonCredentialsNode.SelectSingleNode("./domain")?.InnerText;
connectionInfo.Domain = logonCredentialsNode.SelectSingleNode("./domain")?.InnerText ?? string.Empty;
}
else
{
@@ -165,10 +178,12 @@ namespace mRemoteNG.Config.Serializers
var connectionSettingsNode = xmlNode.SelectSingleNode("./connectionSettings");
if (connectionSettingsNode?.Attributes?["inherit"]?.Value == "None")
{
connectionInfo.UseConsoleSession = bool.Parse(connectionSettingsNode.SelectSingleNode("./connectToConsole")?.InnerText ?? "false");
if (bool.TryParse(connectionSettingsNode.SelectSingleNode("./connectToConsole")?.InnerText, out var useConsole))
connectionInfo.UseConsoleSession = useConsole;
// ./startProgram
// ./workingDir
connectionInfo.Port = Convert.ToInt32(connectionSettingsNode.SelectSingleNode("./port")?.InnerText);
if (int.TryParse(connectionSettingsNode.SelectSingleNode("./port")?.InnerText, out var port))
connectionInfo.Port = port;
}
else
{
@@ -179,14 +194,18 @@ namespace mRemoteNG.Config.Serializers
var gatewaySettingsNode = xmlNode.SelectSingleNode("./gatewaySettings");
if (gatewaySettingsNode?.Attributes?["inherit"]?.Value == "None")
{
connectionInfo.RDGatewayUsageMethod = gatewaySettingsNode.SelectSingleNode("./enabled")?.InnerText == "True" ? RdpProtocol.RDGatewayUsageMethod.Always : RdpProtocol.RDGatewayUsageMethod.Never;
connectionInfo.RDGatewayHostname = gatewaySettingsNode.SelectSingleNode("./hostName")?.InnerText;
connectionInfo.RDGatewayUsername = gatewaySettingsNode.SelectSingleNode("./userName")?.InnerText;
connectionInfo.RDGatewayUsageMethod = gatewaySettingsNode.SelectSingleNode("./enabled")?.InnerText == "True"
? RdpProtocol.RDGatewayUsageMethod.Always
: RdpProtocol.RDGatewayUsageMethod.Never;
connectionInfo.RDGatewayHostname = gatewaySettingsNode.SelectSingleNode("./hostName")?.InnerText ?? string.Empty;
connectionInfo.RDGatewayUsername = gatewaySettingsNode.SelectSingleNode("./userName")?.InnerText ?? string.Empty;
var passwordNode = gatewaySettingsNode.SelectSingleNode("./password");
connectionInfo.RDGatewayPassword = passwordNode?.Attributes?["storeAsClearText"]?.Value == "True" ? passwordNode.InnerText : DecryptRdcManPassword(passwordNode?.InnerText);
connectionInfo.RDGatewayPassword = passwordNode?.Attributes?["storeAsClearText"]?.Value == "True"
? passwordNode.InnerText
: DecryptRdcManPassword(passwordNode?.InnerText);
connectionInfo.RDGatewayDomain = gatewaySettingsNode.SelectSingleNode("./domain")?.InnerText;
connectionInfo.RDGatewayDomain = gatewaySettingsNode.SelectSingleNode("./domain")?.InnerText ?? string.Empty;
// ./logonMethod
// ./localBypass
// ./credSharing
@@ -203,15 +222,10 @@ namespace mRemoteNG.Config.Serializers
var remoteDesktopNode = xmlNode.SelectSingleNode("./remoteDesktop");
if (remoteDesktopNode?.Attributes?["inherit"]?.Value == "None")
{
var resolutionString = remoteDesktopNode.SelectSingleNode("./size")?.InnerText.Replace(" ", "");
try
{
connectionInfo.Resolution = (RdpProtocol.RDPResolutions)Enum.Parse(typeof(RdpProtocol.RDPResolutions), "Res" + resolutionString);
}
catch (ArgumentException)
{
connectionInfo.Resolution = RdpProtocol.RDPResolutions.FitToWindow;
}
connectionInfo.Resolution =
Enum.TryParse<RdpProtocol.RDPResolutions>(remoteDesktopNode.SelectSingleNode("./size")?.InnerText.Replace(" ", ""), true, out var rdpResolution)
? rdpResolution
: RdpProtocol.RDPResolutions.FitToWindow;
if (remoteDesktopNode.SelectSingleNode("./sameSizeAsClientArea")?.InnerText == "True")
{
@@ -223,9 +237,8 @@ namespace mRemoteNG.Config.Serializers
connectionInfo.Resolution = RdpProtocol.RDPResolutions.Fullscreen;
}
var colorDepth = remoteDesktopNode.SelectSingleNode("./colorDepth")?.InnerText;
if (colorDepth != null)
connectionInfo.Colors = (RdpProtocol.RDPColors)Enum.Parse(typeof(RdpProtocol.RDPColors), colorDepth);
if (Enum.TryParse<RdpProtocol.RDPColors>(remoteDesktopNode.SelectSingleNode("./colorDepth")?.InnerText, true, out var rdpColors))
connectionInfo.Colors = rdpColors;
}
else
{
@@ -274,10 +287,17 @@ namespace mRemoteNG.Config.Serializers
}
// ./redirectClipboard
connectionInfo.RedirectDiskDrives = bool.Parse(localResourcesNode?.SelectSingleNode("./redirectDrives")?.InnerText ?? "false");
connectionInfo.RedirectPorts = bool.Parse(localResourcesNode?.SelectSingleNode("./redirectPorts")?.InnerText ?? "false");
connectionInfo.RedirectPrinters = bool.Parse(localResourcesNode?.SelectSingleNode("./redirectPrinters")?.InnerText ?? "false");
connectionInfo.RedirectSmartCards = bool.Parse(localResourcesNode?.SelectSingleNode("./redirectSmartCards")?.InnerText ?? "false");
if (bool.TryParse(localResourcesNode?.SelectSingleNode("./redirectDrives")?.InnerText, out var redirectDisks))
connectionInfo.RedirectDiskDrives = redirectDisks;
if (bool.TryParse(localResourcesNode?.SelectSingleNode("./redirectPorts")?.InnerText, out var redirectPorts))
connectionInfo.RedirectPorts = redirectPorts;
if (bool.TryParse(localResourcesNode?.SelectSingleNode("./redirectPrinters")?.InnerText, out var redirectPrinters))
connectionInfo.RedirectPrinters = redirectPrinters;
if (bool.TryParse(localResourcesNode?.SelectSingleNode("./redirectSmartCards")?.InnerText, out var redirectSmartCards))
connectionInfo.RedirectSmartCards = redirectSmartCards;
}
else
{

View File

@@ -1,5 +1,10 @@
using mRemoteNG.App;
using System;
using System.IO;
using System.Threading;
using System.Windows.Forms;
using mRemoteNG.App;
using mRemoteNG.App.Info;
using mRemoteNG.Config;
using mRemoteNG.Config.Connections;
using mRemoteNG.Config.Connections.Multiuser;
using mRemoteNG.Config.DataProviders;
@@ -12,15 +17,10 @@ using mRemoteNG.Tools;
using mRemoteNG.Tree;
using mRemoteNG.Tree.Root;
using mRemoteNG.UI;
using System;
using System.IO;
using System.Threading;
using System.Windows.Forms;
using mRemoteNG.Config;
namespace mRemoteNG.Connection
{
public class ConnectionsService
public class ConnectionsService
{
private static readonly object SaveLock = new object();
private readonly PuttySessionsManager _puttySessionsManager;
@@ -171,6 +171,19 @@ namespace mRemoteNG.Connection
SaveConnections();
}
/// <summary>
/// All calls to <see cref="SaveConnections()"/> or <see cref="SaveConnectionsAsync"/>
/// will be deferred until the returned <see cref="DisposableAction"/> is disposed.
/// Once disposed, this will immediately executes a single <see cref="SaveConnections()"/>
/// or <see cref="SaveConnectionsAsync"/> if one has been requested.
/// Place this call in a 'using' block to represent a batched saving context.
/// </summary>
/// <returns></returns>
public DisposableAction BatchedSavingContext()
{
return new DisposableAction(BeginBatchingSaves, EndBatchingSaves);
}
/// <summary>
/// Saves the currently loaded <see cref="ConnectionTreeModel"/> with
/// no <see cref="SaveFilter"/>.

View File

@@ -13,7 +13,7 @@ using mRemoteNG.Tools.Cmdline;
namespace mRemoteNG.Connection.Protocol
{
public class PuttyBase : ProtocolBase
{
{
private const int IDM_RECONF = 0x50; // PuTTY Settings Menu ID
private bool _isPuttyNg;
@@ -42,7 +42,7 @@ namespace mRemoteNG.Connection.Protocol
Event_Closed(this);
}
#endregion
#region Public Methods
public override bool Connect()
{
@@ -62,11 +62,11 @@ namespace mRemoteNG.Connection.Protocol
var arguments = new CommandLineArguments {EscapeForShell = false};
arguments.Add("-load", InterfaceControl.Info.PuttySession);
if (!(InterfaceControl.Info is PuttySessionInfo))
{
arguments.Add("-" + PuttyProtocol);
if (PuttyProtocol == Putty_Protocol.ssh)
{
var username = "";
@@ -89,7 +89,7 @@ namespace mRemoteNG.Connection.Protocol
break;
}
}
if (!string.IsNullOrEmpty(InterfaceControl.Info?.Password))
{
password = InterfaceControl.Info.Password;
@@ -102,9 +102,9 @@ namespace mRemoteNG.Connection.Protocol
password = cryptographyProvider.Decrypt(Settings.Default.DefaultPassword, Runtime.EncryptionKey);
}
}
arguments.Add("-" + (int)PuttySSHVersion);
if (((int)Force & (int)ConnectionInfo.Force.NoCredentials) != (int)ConnectionInfo.Force.NoCredentials)
{
if (!string.IsNullOrEmpty(username))
@@ -117,24 +117,24 @@ namespace mRemoteNG.Connection.Protocol
}
}
}
arguments.Add("-P", InterfaceControl.Info.Port.ToString());
arguments.Add(InterfaceControl.Info.Hostname);
}
if (_isPuttyNg)
{
arguments.Add("-hwndparent", InterfaceControl.Handle.ToString());
}
PuttyProcess.StartInfo.Arguments = arguments.ToString();
PuttyProcess.EnableRaisingEvents = true;
PuttyProcess.Exited += ProcessExited;
PuttyProcess.Start();
PuttyProcess.WaitForInputIdle(Settings.Default.MaxPuttyWaitTime * 1000);
var startTicks = Environment.TickCount;
while (PuttyHandle.ToInt32() == 0 & Environment.TickCount < startTicks + Settings.Default.MaxPuttyWaitTime * 1000)
{
@@ -153,17 +153,17 @@ namespace mRemoteNG.Connection.Protocol
Thread.Sleep(0);
}
}
if (!_isPuttyNg)
{
NativeMethods.SetParent(PuttyHandle, InterfaceControl.Handle);
}
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, Language.strPuttyStuff, true);
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, string.Format(Language.strPuttyHandle, PuttyHandle), true);
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, string.Format(Language.strPuttyTitle, PuttyProcess.MainWindowTitle), true);
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, string.Format(Language.strPuttyParentHandle, InterfaceControl.Parent.Handle), true);
Resize(this, new EventArgs());
base.Connect();
return true;
@@ -174,7 +174,7 @@ namespace mRemoteNG.Connection.Protocol
return false;
}
}
public override void Focus()
{
try
@@ -190,7 +190,7 @@ namespace mRemoteNG.Connection.Protocol
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, Language.strPuttyFocusFailed + Environment.NewLine + ex.Message, true);
}
}
public override void Resize(object sender, EventArgs e)
{
try
@@ -200,20 +200,28 @@ namespace mRemoteNG.Connection.Protocol
return;
}
var left = -(SystemInformation.FrameBorderSize.Width + SystemInformation.HorizontalResizeBorderThickness);
var top = -(SystemInformation.CaptionHeight + SystemInformation.FrameBorderSize.Height + SystemInformation.VerticalResizeBorderThickness);
var width = InterfaceControl.Width + (SystemInformation.FrameBorderSize.Width + SystemInformation.HorizontalResizeBorderThickness) * 2;
var height = InterfaceControl.Height + SystemInformation.CaptionHeight +
(SystemInformation.FrameBorderSize.Height + SystemInformation.VerticalResizeBorderThickness) * 2;
if (_isPuttyNg)
{
// PuTTYNG 0.70.0.1 and later doesn't have any window borders
NativeMethods.MoveWindow(PuttyHandle, 0, 0, InterfaceControl.Width, InterfaceControl.Height, true);
}
else
{
var left = -(SystemInformation.FrameBorderSize.Width + SystemInformation.HorizontalResizeBorderThickness);
var top = -(SystemInformation.CaptionHeight + SystemInformation.FrameBorderSize.Height + SystemInformation.VerticalResizeBorderThickness);
var width = InterfaceControl.Width + (SystemInformation.FrameBorderSize.Width + SystemInformation.HorizontalResizeBorderThickness) * 2;
var height = InterfaceControl.Height + SystemInformation.CaptionHeight + (SystemInformation.FrameBorderSize.Height +
SystemInformation.VerticalResizeBorderThickness) * 2;
NativeMethods.MoveWindow(PuttyHandle, left, top, width, height, true);
}
NativeMethods.MoveWindow(PuttyHandle, left, top, width, height, true);
}
}
catch (Exception ex)
{
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, Language.strPuttyResizeFailed + Environment.NewLine + ex.Message, true);
}
}
public override void Close()
{
try
@@ -227,7 +235,7 @@ namespace mRemoteNG.Connection.Protocol
{
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, Language.strPuttyKillFailed + Environment.NewLine + ex.Message, true);
}
try
{
PuttyProcess.Dispose();
@@ -236,10 +244,10 @@ namespace mRemoteNG.Connection.Protocol
{
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, Language.strPuttyDisposeFailed + Environment.NewLine + ex.Message, true);
}
base.Close();
}
public void ShowSettingsDialog()
{
try
@@ -253,7 +261,7 @@ namespace mRemoteNG.Connection.Protocol
}
}
#endregion
#region Enums
protected enum Putty_Protocol

View File

@@ -14,7 +14,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyDescription("Multi-protocol remote connections manager")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("mRemoteNG")]
[assembly: AssemblyCopyright("Copyright © 2018 mRemoteNG Dev Team; 2010-2013 Riley McArdle; 2007-2009 Felix Deimel")]
[assembly: AssemblyCopyright("Copyright © 2019 mRemoteNG Dev Team; 2010-2013 Riley McArdle; 2007-2009 Felix Deimel")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
@@ -33,5 +33,5 @@ using System.Runtime.InteropServices;
// by using the '*' as shown below:
// <Assembly: AssemblyVersion("1.0.*")>
[assembly: AssemblyVersion("1.76.13.*")]
[assembly: AssemblyVersion("1.76.20.*")]
[assembly: NeutralResourcesLanguage("en")]

View File

@@ -12,7 +12,7 @@ namespace mRemoteNG {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.7.0.0")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.9.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
@@ -2722,5 +2722,17 @@ namespace mRemoteNG {
this["StartUpPanelName"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("False")]
public bool OverrideFIPSCheck {
get {
return ((bool)(this["OverrideFIPSCheck"]));
}
set {
this["OverrideFIPSCheck"] = value;
}
}
}
}

View File

@@ -677,5 +677,8 @@
<Setting Name="StartUpPanelName" Type="System.String" Scope="User">
<Value Profile="(Default)">General</Value>
</Setting>
<Setting Name="OverrideFIPSCheck" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
</Settings>
</SettingsFile>

View File

@@ -2000,11 +2000,11 @@ namespace mRemoteNG {
}
/// <summary>
/// Looks up a localized string similar to The Windows security setting, &quot;System cryptography: Use FIPS compliant algorithms for encryption, hashing, and signing&quot;, is enabled. This setting is not compatible with {0}.
/// Looks up a localized string similar to The Windows security setting, &quot;System cryptography: Use FIPS compliant algorithms for encryption, hashing, and signing&quot;, is enabled.
///
///See the Microsoft Support article at http://support.microsoft.com/kb/811833 for more information.
///
///{0} will now close..
///{0} is not fully FIPS compliant. Click OK to proceed at your own discretion, or Cancel to Exit..
/// </summary>
internal static string strErrorFipsPolicyIncompatible {
get {

View File

@@ -655,11 +655,11 @@ Starting with new connections file.</value>
<value>Encryption failed. {0}</value>
</data>
<data name="strErrorFipsPolicyIncompatible" xml:space="preserve">
<value>The Windows security setting, "System cryptography: Use FIPS compliant algorithms for encryption, hashing, and signing", is enabled. This setting is not compatible with {0}.
<value>The Windows security setting, "System cryptography: Use FIPS compliant algorithms for encryption, hashing, and signing", is enabled.
See the Microsoft Support article at http://support.microsoft.com/kb/811833 for more information.
{0} will now close.</value>
{0} is not fully FIPS compliant. Click OK to proceed at your own discretion, or Cancel to Exit.</value>
</data>
<data name="strErrors" xml:space="preserve">
<value>Errors</value>

Binary file not shown.

View File

@@ -0,0 +1,45 @@
using System;
namespace mRemoteNG.Tools
{
/// <summary>
/// Represents an action that will be executed when the <see cref="Dispose"/>
/// method is called. Useful for creating Using blocks around logical start/end
/// actions.
/// </summary>
public class DisposableAction : IDisposable
{
private bool _isDisposed;
private readonly Action _disposeAction;
/// <summary>
///
/// </summary>
/// <param name="initializeAction">
/// An <see cref="Action"/> that should be performed immediately
/// when this object is initialized. It should return quickly.
/// </param>
/// <param name="disposeAction">
/// An <see cref="Action"/> to be executed when this object is disposed.
/// </param>
public DisposableAction(Action initializeAction, Action disposeAction)
{
initializeAction();
_disposeAction = disposeAction;
}
public void Dispose()
{
Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
if (!disposing || _isDisposed)
return;
_isDisposed = true;
_disposeAction();
}
}
}

View File

@@ -698,6 +698,9 @@
<setting name="StartUpPanelName" serializeAs="String">
<value>General</value>
</setting>
<setting name="OverrideFIPSCheck" serializeAs="String">
<value>False</value>
</setting>
</mRemoteNG.Settings>
</userSettings>
<applicationSettings>

View File

@@ -318,6 +318,7 @@
<Compile Include="Tools\Cmdline\StartupArgumentsInterpreter.cs" />
<Compile Include="Tools\CustomCollections\CollectionUpdatedEventArgs.cs" />
<Compile Include="Settings.cs" />
<Compile Include="Tools\DisposableAction.cs" />
<Compile Include="Tools\Extensions.cs" />
<Compile Include="Tools\ExternalToolArgumentParser.cs" />
<Compile Include="Tools\Cmdline\CmdArgumentsInterpreter.cs" />