inserted a new page in the upgrade process to view harvested credentials

This commit is contained in:
David Sparer
2018-12-30 14:33:42 -06:00
parent 63ebef56b0
commit 15f028157e
10 changed files with 375 additions and 176 deletions

View File

@@ -36,7 +36,7 @@ namespace mRemoteNGTests.Config
var connection = new ConnectionInfo { Username = "myuser", Domain = "somedomain", Password = "mypass" };
var xdoc = CreateTestData(connection);
var credentials = _credentialHarvester.Harvest(xdoc, _key);
Assert.That(credentials.Single().Username, Is.EqualTo(connection.Username));
Assert.That(credentials.DistinctCredentialRecords.Single().Username, Is.EqualTo(connection.Username));
}
[Test]
@@ -45,7 +45,7 @@ namespace mRemoteNGTests.Config
var connection = new ConnectionInfo { Username = "myuser", Domain = "somedomain", Password = "mypass" };
var xdoc = CreateTestData(connection);
var credentials = _credentialHarvester.Harvest(xdoc, _key);
Assert.That(credentials.Single().Domain, Is.EqualTo(connection.Domain));
Assert.That(credentials.DistinctCredentialRecords.Single().Domain, Is.EqualTo(connection.Domain));
}
[Test]
@@ -54,7 +54,7 @@ namespace mRemoteNGTests.Config
var connection = new ConnectionInfo { Username = "myuser", Domain = "somedomain", Password = "mypass" };
var xdoc = CreateTestData(connection);
var credentials = _credentialHarvester.Harvest(xdoc, _key);
Assert.That(credentials.Single().Password.ConvertToUnsecureString(), Is.EqualTo(connection.Password));
Assert.That(credentials.DistinctCredentialRecords.Single().Password.ConvertToUnsecureString(), Is.EqualTo(connection.Password));
}
[Test]
@@ -96,8 +96,7 @@ namespace mRemoteNGTests.Config
var connection = new ConnectionInfo { Username = "myuser", Domain = "somedomain", Password = "mypass" };
var connectionGuid = Guid.Parse(connection.ConstantID);
var xdoc = CreateTestData(connection);
_credentialHarvester.Harvest(xdoc, _key);
var map = _credentialHarvester.ConnectionToCredentialMap;
var map = _credentialHarvester.Harvest(xdoc, _key);
Assert.That(map[connectionGuid].Username, Is.EqualTo(connection.Username));
}
@@ -111,8 +110,7 @@ namespace mRemoteNGTests.Config
var xdoc = CreateTestData(container);
var con1Id = Guid.Parse(con1.ConstantID);
var con2Id = Guid.Parse(con2.ConstantID);
_credentialHarvester.Harvest(xdoc, _key);
var map = _credentialHarvester.ConnectionToCredentialMap;
var map = _credentialHarvester.Harvest(xdoc, _key);
Assert.That(map[con1Id], Is.EqualTo(map[con2Id]));
}

View File

@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using mRemoteNG.Credential;
namespace mRemoteNG.Config
{
public class ConnectionToCredentialMap : Dictionary<Guid, ICredentialRecord>
{
private readonly IEqualityComparer<ICredentialRecord> _credentialComparer = new CredentialDomainUserPasswordComparer();
public IEnumerable<ICredentialRecord> DistinctCredentialRecords => Values.Distinct(_credentialComparer);
}
}

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Security;
using System.Xml.Linq;
using mRemoteNG.Connection;
using mRemoteNG.Credential;
using mRemoteNG.Security;
using mRemoteNG.Security.Factories;
@@ -13,16 +14,21 @@ namespace mRemoteNG.Config
{
private readonly IEqualityComparer<ICredentialRecord> _credentialComparer = new CredentialDomainUserPasswordComparer();
// maps a connectioninfo (by its id) to the credential object that was harvested
public Dictionary<Guid, ICredentialRecord> ConnectionToCredentialMap { get; } = new Dictionary<Guid, ICredentialRecord>();
public IEnumerable<ICredentialRecord> Harvest(XDocument xDocument, SecureString decryptionKey)
/// <summary>
/// Maps a <see cref="ConnectionInfo"/> (by its id) to the <see cref="ICredentialRecord"/>
/// object that was harvested
/// </summary>
/// <param name="xDocument"></param>
/// <param name="decryptionKey"></param>
/// <returns></returns>
public ConnectionToCredentialMap Harvest(XDocument xDocument, SecureString decryptionKey)
{
if (xDocument == null)
throw new ArgumentNullException(nameof(xDocument));
var cryptoProvider = new CryptoProviderFactoryFromXml(xDocument.Root).Build();
var credentialMap = new ConnectionToCredentialMap();
foreach (var element in xDocument.Descendants("Node"))
{
if (!EntryHasSomeCredentialData(element)) continue;
@@ -34,16 +40,16 @@ namespace mRemoteNG.Config
//error
}
if (ConnectionToCredentialMap.Values.Contains(newCredential, _credentialComparer))
if (credentialMap.Values.Contains(newCredential, _credentialComparer))
{
var existingCredential = ConnectionToCredentialMap.Values.First(record => _credentialComparer.Equals(newCredential, record));
ConnectionToCredentialMap.Add(connectionId, existingCredential);
var existingCredential = credentialMap.Values.First(record => _credentialComparer.Equals(newCredential, record));
credentialMap.Add(connectionId, existingCredential);
}
else
ConnectionToCredentialMap.Add(connectionId, newCredential);
credentialMap.Add(connectionId, newCredential);
}
return ConnectionToCredentialMap.Values.Distinct(_credentialComparer);
return credentialMap;
}
private ICredentialRecord BuildCredential(XElement element, ICryptographyProvider cryptographyProvider, SecureString decryptionKey)

View File

@@ -1,11 +1,9 @@
using System;
using System.Collections.Generic;
using System.Security;
using System.Xml.Linq;
using mRemoteNG.App;
using mRemoteNG.Connection;
using mRemoteNG.Credential;
using mRemoteNG.Credential.Repositories;
using mRemoteNG.Security.Authentication;
using mRemoteNG.Security.Factories;
using mRemoteNG.Tools;
@@ -14,34 +12,22 @@ using System.Linq;
namespace mRemoteNG.Config.Serializers.Versioning
{
public class XmlCredentialManagerUpgrader : IDeserializer<string, ConnectionTreeModel>
public class XmlCredentialManagerUpgrader
{
private readonly CredentialService _credentialsService;
private readonly IDeserializer<string, ConnectionTreeModel> _decoratedDeserializer;
private readonly SecureString _newRepoPassword;
private readonly IDeserializer<string, ConnectionTreeModel> _deserializer;
public string CredentialFilePath { get; set; }
public XmlCredentialManagerUpgrader(
CredentialService credentialsService,
string credentialFilePath,
IDeserializer<string, ConnectionTreeModel> decoratedDeserializer,
SecureString newRepoPassword)
public XmlCredentialManagerUpgrader(IDeserializer<string, ConnectionTreeModel> decoratedDeserializer)
{
_credentialsService = credentialsService.ThrowIfNull(nameof(credentialsService));
CredentialFilePath = credentialFilePath;
_newRepoPassword = newRepoPassword;
_decoratedDeserializer = decoratedDeserializer.ThrowIfNull(nameof(decoratedDeserializer));
_deserializer = decoratedDeserializer.ThrowIfNull(nameof(decoratedDeserializer));
}
public ConnectionTreeModel Deserialize(string serializedData)
public ConnectionTreeModel Deserialize(string serializedData, ConnectionToCredentialMap upgradeMap)
{
var serializedDataAsXDoc = EnsureConnectionXmlElementsHaveIds(serializedData);
var upgradeMap = UpgradeUserFilesForCredentialManager(serializedDataAsXDoc);
var serializedDataWithIds = $"{serializedDataAsXDoc.Declaration}{serializedDataAsXDoc}";
var connectionTreeModel = _decoratedDeserializer.Deserialize(serializedDataWithIds);
var connectionTreeModel = _deserializer.Deserialize(serializedDataWithIds);
if (upgradeMap != null)
ApplyCredentialMapping(upgradeMap, connectionTreeModel.GetRecursiveChildList());
@@ -58,7 +44,7 @@ namespace mRemoteNG.Config.Serializers.Versioning
return xdoc;
}
public Dictionary<Guid, ICredentialRecord> UpgradeUserFilesForCredentialManager(XDocument xdoc)
public ConnectionToCredentialMap UpgradeUserFilesForCredentialManager(XDocument xdoc)
{
if (!CredentialManagerUpgradeNeeded(xdoc))
{
@@ -76,13 +62,7 @@ namespace mRemoteNG.Config.Serializers.Versioning
var credentialHarvester = new CredentialHarvester();
var harvestedCredentials = credentialHarvester.Harvest(xdoc, keyForOldConnectionFile);
var newCredentialRepository = BuildXmlCredentialRepo(_newRepoPassword);
AddHarvestedCredentialsToRepo(harvestedCredentials, newCredentialRepository);
newCredentialRepository.SaveCredentials(_newRepoPassword);
_credentialsService.AddRepository(newCredentialRepository);
return credentialHarvester.ConnectionToCredentialMap;
return harvestedCredentials;
}
/// <summary>
@@ -100,33 +80,7 @@ namespace mRemoteNG.Config.Serializers.Versioning
n.Attribute("Password") != null);
}
private ICredentialRepository BuildXmlCredentialRepo(SecureString newCredRepoKey)
{
var repositoryConfig = new CredentialRepositoryConfig
{
Source = CredentialFilePath,
Title = "Converted Credentials",
TypeName = "Xml",
Key = newCredRepoKey
};
var xmlRepoFactory = _credentialsService.GetRepositoryFactoryForConfig(repositoryConfig);
if (!xmlRepoFactory.Any())
throw new CredentialRepositoryTypeNotSupportedException(repositoryConfig.TypeName);
var newRepo = xmlRepoFactory.First().Build(repositoryConfig);
newRepo.LoadCredentials(newCredRepoKey);
return newRepo;
}
private void AddHarvestedCredentialsToRepo(IEnumerable<ICredentialRecord> harvestedCredentials, ICredentialRepository repo)
{
foreach (var credential in harvestedCredentials)
repo.CredentialRecords.Add(credential);
}
public void ApplyCredentialMapping(IDictionary<Guid, ICredentialRecord> map, IEnumerable<AbstractConnectionRecord> connectionRecords)
private void ApplyCredentialMapping(IDictionary<Guid, ICredentialRecord> map, IEnumerable<AbstractConnectionRecord> connectionRecords)
{
foreach (var connectionInfo in connectionRecords)
{

View File

@@ -189,7 +189,7 @@ namespace mRemoteNG.Connection
get
{
var credential = CredentialRecordId
.Select(guid => Runtime.CredentialService.RepositoryList.GetCredentialRecord(guid))
.Select(guid => Runtime.CredentialService.GetCredentialRecord(guid))
.FirstOrDefault();
return credential ?? new PlaceholderCredentialRecord(CredentialRecordId);
}

View File

@@ -28,32 +28,24 @@
/// </summary>
private void InitializeComponent()
{
this.labelFirstPasswordBox = new Controls.Base.NGLabel();
this.labelSecondPasswordBox = new Controls.Base.NGLabel();
this.labelPasswordsDontMatch = new Controls.Base.NGLabel();
this.imgError = new System.Windows.Forms.PictureBox();
this.labelPasswordsDontMatch = new mRemoteNG.UI.Controls.Base.NGLabel();
this.labelSecondPasswordBox = new mRemoteNG.UI.Controls.Base.NGLabel();
this.labelFirstPasswordBox = new mRemoteNG.UI.Controls.Base.NGLabel();
this.secureTextBox2 = new mRemoteNG.UI.Controls.SecureTextBox();
this.secureTextBox1 = new mRemoteNG.UI.Controls.SecureTextBox();
((System.ComponentModel.ISupportInitialize)(this.imgError)).BeginInit();
this.SuspendLayout();
//
// labelFirstPasswordBox
// imgError
//
this.labelFirstPasswordBox.AutoSize = true;
this.labelFirstPasswordBox.Location = new System.Drawing.Point(-3, 0);
this.labelFirstPasswordBox.Name = "labelFirstPasswordBox";
this.labelFirstPasswordBox.Size = new System.Drawing.Size(78, 13);
this.labelFirstPasswordBox.TabIndex = 2;
this.labelFirstPasswordBox.Text = "New Password";
//
// labelSecondPasswordBox
//
this.labelSecondPasswordBox.AutoSize = true;
this.labelSecondPasswordBox.Location = new System.Drawing.Point(-3, 42);
this.labelSecondPasswordBox.Name = "labelSecondPasswordBox";
this.labelSecondPasswordBox.Size = new System.Drawing.Size(79, 13);
this.labelSecondPasswordBox.TabIndex = 3;
this.labelSecondPasswordBox.Text = "VerifyPassword";
this.imgError.Image = global::mRemoteNG.Resources.ErrorSmall;
this.imgError.Location = new System.Drawing.Point(3, 81);
this.imgError.Name = "imgError";
this.imgError.Size = new System.Drawing.Size(16, 16);
this.imgError.TabIndex = 5;
this.imgError.TabStop = false;
this.imgError.Visible = false;
//
// labelPasswordsDontMatch
//
@@ -65,15 +57,23 @@
this.labelPasswordsDontMatch.Text = "Passwords do not match";
this.labelPasswordsDontMatch.Visible = false;
//
// imgError
// labelSecondPasswordBox
//
this.imgError.Image = global::mRemoteNG.Resources.ErrorSmall;
this.imgError.Location = new System.Drawing.Point(3, 81);
this.imgError.Name = "imgError";
this.imgError.Size = new System.Drawing.Size(16, 16);
this.imgError.TabIndex = 5;
this.imgError.TabStop = false;
this.imgError.Visible = false;
this.labelSecondPasswordBox.AutoSize = true;
this.labelSecondPasswordBox.Location = new System.Drawing.Point(-3, 42);
this.labelSecondPasswordBox.Name = "labelSecondPasswordBox";
this.labelSecondPasswordBox.Size = new System.Drawing.Size(79, 13);
this.labelSecondPasswordBox.TabIndex = 3;
this.labelSecondPasswordBox.Text = "VerifyPassword";
//
// labelFirstPasswordBox
//
this.labelFirstPasswordBox.AutoSize = true;
this.labelFirstPasswordBox.Location = new System.Drawing.Point(-3, 0);
this.labelFirstPasswordBox.Name = "labelFirstPasswordBox";
this.labelFirstPasswordBox.Size = new System.Drawing.Size(78, 13);
this.labelFirstPasswordBox.TabIndex = 2;
this.labelFirstPasswordBox.Text = "New Password";
//
// secureTextBox2
//
@@ -95,8 +95,9 @@
//
// NewPasswordWithVerification
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.BackColor = System.Drawing.Color.Transparent;
this.Controls.Add(this.imgError);
this.Controls.Add(this.labelPasswordsDontMatch);
this.Controls.Add(this.labelSecondPasswordBox);

View File

@@ -46,6 +46,9 @@ namespace mRemoteNG.UI.Controls
public NewPasswordWithVerification()
{
InitializeComponent();
var display = new DisplayProperties();
secureTextBox1.Width = display.ScaleWidth(Width);
secureTextBox2.Width = display.ScaleWidth(Width);
secureTextBox1.TextChanged += OnSecureTextBoxTextChanged;
secureTextBox2.TextChanged += OnSecureTextBoxTextChanged;
}

View File

@@ -37,10 +37,19 @@
this.labelConfConsPathHeaderOnTab1 = new mRemoteNG.UI.Controls.Base.NGLabel();
this.buttonExit = new mRemoteNG.UI.Controls.Base.NGButton();
this.labelDescriptionOfUpgrade = new mRemoteNG.UI.Controls.Base.NGLabel();
this.buttonPerformUpgrade = new mRemoteNG.UI.Controls.Base.NGButton();
this.buttonBeginUpgrade = new mRemoteNG.UI.Controls.Base.NGButton();
this.buttonNewFile = new mRemoteNG.UI.Controls.Base.NGButton();
this.buttonOpenFile = new mRemoteNG.UI.Controls.Base.NGButton();
this.tabPageUpgradeOptions = new System.Windows.Forms.TabPage();
this.tabPageHarvestedCreds = new System.Windows.Forms.TabPage();
this.olvFoundCredentials = new mRemoteNG.UI.Controls.Base.NGListView();
this.colTitle = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
this.colUsername = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
this.colDomain = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
this.colPassword = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
this.lblCredsFound = new mRemoteNG.UI.Controls.Base.NGLabel();
this.btnCredsBack = new mRemoteNG.UI.Controls.Base.NGButton();
this.btnCredsContinue = new mRemoteNG.UI.Controls.Base.NGButton();
this.tabPageSaveRepo = new System.Windows.Forms.TabPage();
this.textBoxConfConPathTab2 = new mRemoteNG.UI.Controls.Base.NGTextBox();
this.buttonNewRepoPathBrowse = new mRemoteNG.UI.Controls.Base.NGButton();
this.labelWhereToSaveCredFile = new mRemoteNG.UI.Controls.Base.NGLabel();
@@ -49,10 +58,12 @@
this.labelSetPassword = new mRemoteNG.UI.Controls.Base.NGLabel();
this.newRepositoryPasswordEntry = new mRemoteNG.UI.Controls.NewPasswordWithVerification();
this.labelConfConsPathHeaderOnTab2 = new mRemoteNG.UI.Controls.Base.NGLabel();
this.buttonBack = new mRemoteNG.UI.Controls.Base.NGButton();
this.buttonSaveRepoBack = new mRemoteNG.UI.Controls.Base.NGButton();
this.tabControl.SuspendLayout();
this.tabPageWelcome.SuspendLayout();
this.tabPageUpgradeOptions.SuspendLayout();
this.tabPageHarvestedCreds.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.olvFoundCredentials)).BeginInit();
this.tabPageSaveRepo.SuspendLayout();
this.SuspendLayout();
//
// newCredRepoPathDialog
@@ -68,7 +79,8 @@
// tabControl
//
this.tabControl.Controls.Add(this.tabPageWelcome);
this.tabControl.Controls.Add(this.tabPageUpgradeOptions);
this.tabControl.Controls.Add(this.tabPageHarvestedCreds);
this.tabControl.Controls.Add(this.tabPageSaveRepo);
this.tabControl.Dock = System.Windows.Forms.DockStyle.Fill;
this.tabControl.ItemSize = new System.Drawing.Size(60, 20);
this.tabControl.Location = new System.Drawing.Point(0, 0);
@@ -79,12 +91,12 @@
//
// tabPageWelcome
//
this.tabPageWelcome.BackColor = System.Drawing.SystemColors.Control;
this.tabPageWelcome.BackColor = System.Drawing.Color.Transparent;
this.tabPageWelcome.Controls.Add(this.textBoxConfConPathTab1);
this.tabPageWelcome.Controls.Add(this.labelConfConsPathHeaderOnTab1);
this.tabPageWelcome.Controls.Add(this.buttonExit);
this.tabPageWelcome.Controls.Add(this.labelDescriptionOfUpgrade);
this.tabPageWelcome.Controls.Add(this.buttonPerformUpgrade);
this.tabPageWelcome.Controls.Add(this.buttonBeginUpgrade);
this.tabPageWelcome.Controls.Add(this.buttonNewFile);
this.tabPageWelcome.Controls.Add(this.buttonOpenFile);
this.tabPageWelcome.Location = new System.Drawing.Point(4, 24);
@@ -136,17 +148,17 @@
this.labelDescriptionOfUpgrade.TabIndex = 0;
this.labelDescriptionOfUpgrade.Text = resources.GetString("labelDescriptionOfUpgrade.Text");
//
// buttonPerformUpgrade
// buttonBeginUpgrade
//
this.buttonPerformUpgrade._mice = mRemoteNG.UI.Controls.Base.NGButton.MouseState.HOVER;
this.buttonPerformUpgrade.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.buttonPerformUpgrade.Location = new System.Drawing.Point(190, 256);
this.buttonPerformUpgrade.Name = "buttonPerformUpgrade";
this.buttonPerformUpgrade.Size = new System.Drawing.Size(212, 23);
this.buttonPerformUpgrade.TabIndex = 1;
this.buttonPerformUpgrade.Text = "Upgrade";
this.buttonPerformUpgrade.UseVisualStyleBackColor = true;
this.buttonPerformUpgrade.Click += new System.EventHandler(this.buttonPerformUpgrade_Click);
this.buttonBeginUpgrade._mice = mRemoteNG.UI.Controls.Base.NGButton.MouseState.HOVER;
this.buttonBeginUpgrade.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.buttonBeginUpgrade.Location = new System.Drawing.Point(190, 256);
this.buttonBeginUpgrade.Name = "buttonBeginUpgrade";
this.buttonBeginUpgrade.Size = new System.Drawing.Size(212, 23);
this.buttonBeginUpgrade.TabIndex = 1;
this.buttonBeginUpgrade.Text = "Upgrade";
this.buttonBeginUpgrade.UseVisualStyleBackColor = true;
this.buttonBeginUpgrade.Click += new System.EventHandler(this.buttonBeginUpgrade_Click);
//
// buttonNewFile
//
@@ -173,24 +185,128 @@
this.buttonOpenFile.UseVisualStyleBackColor = true;
this.buttonOpenFile.Click += new System.EventHandler(this.buttonOpenFile_Click);
//
// tabPageUpgradeOptions
// tabPageHarvestedCreds
//
this.tabPageUpgradeOptions.BackColor = System.Drawing.SystemColors.Control;
this.tabPageUpgradeOptions.Controls.Add(this.textBoxConfConPathTab2);
this.tabPageUpgradeOptions.Controls.Add(this.buttonNewRepoPathBrowse);
this.tabPageUpgradeOptions.Controls.Add(this.labelWhereToSaveCredFile);
this.tabPageUpgradeOptions.Controls.Add(this.textBoxCredRepoPath);
this.tabPageUpgradeOptions.Controls.Add(this.buttonExecuteUpgrade);
this.tabPageUpgradeOptions.Controls.Add(this.labelSetPassword);
this.tabPageUpgradeOptions.Controls.Add(this.newRepositoryPasswordEntry);
this.tabPageUpgradeOptions.Controls.Add(this.labelConfConsPathHeaderOnTab2);
this.tabPageUpgradeOptions.Controls.Add(this.buttonBack);
this.tabPageUpgradeOptions.Location = new System.Drawing.Point(4, 24);
this.tabPageUpgradeOptions.Name = "tabPageUpgradeOptions";
this.tabPageUpgradeOptions.Padding = new System.Windows.Forms.Padding(3);
this.tabPageUpgradeOptions.Size = new System.Drawing.Size(609, 374);
this.tabPageUpgradeOptions.TabIndex = 1;
this.tabPageUpgradeOptions.Text = "upgradePage";
this.tabPageHarvestedCreds.BackColor = System.Drawing.Color.Transparent;
this.tabPageHarvestedCreds.Controls.Add(this.olvFoundCredentials);
this.tabPageHarvestedCreds.Controls.Add(this.lblCredsFound);
this.tabPageHarvestedCreds.Controls.Add(this.btnCredsBack);
this.tabPageHarvestedCreds.Controls.Add(this.btnCredsContinue);
this.tabPageHarvestedCreds.Location = new System.Drawing.Point(4, 24);
this.tabPageHarvestedCreds.Name = "tabPageHarvestedCreds";
this.tabPageHarvestedCreds.Padding = new System.Windows.Forms.Padding(3);
this.tabPageHarvestedCreds.Size = new System.Drawing.Size(609, 374);
this.tabPageHarvestedCreds.TabIndex = 2;
this.tabPageHarvestedCreds.Text = "harvestedCreds";
//
// olvFoundCredentials
//
this.olvFoundCredentials.AllColumns.Add(this.colTitle);
this.olvFoundCredentials.AllColumns.Add(this.colUsername);
this.olvFoundCredentials.AllColumns.Add(this.colDomain);
this.olvFoundCredentials.AllColumns.Add(this.colPassword);
this.olvFoundCredentials.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.olvFoundCredentials.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.colTitle,
this.colUsername,
this.colDomain,
this.colPassword});
this.olvFoundCredentials.Cursor = System.Windows.Forms.Cursors.Default;
this.olvFoundCredentials.DecorateLines = true;
this.olvFoundCredentials.HasCollapsibleGroups = false;
this.olvFoundCredentials.Location = new System.Drawing.Point(0, 31);
this.olvFoundCredentials.Name = "olvFoundCredentials";
this.olvFoundCredentials.ShowFilterMenuOnRightClick = false;
this.olvFoundCredentials.Size = new System.Drawing.Size(609, 308);
this.olvFoundCredentials.SortGroupItemsByPrimaryColumn = false;
this.olvFoundCredentials.TabIndex = 4;
this.olvFoundCredentials.UseCompatibleStateImageBehavior = false;
this.olvFoundCredentials.UseNotifyPropertyChanged = true;
this.olvFoundCredentials.UseOverlays = false;
this.olvFoundCredentials.View = System.Windows.Forms.View.Details;
//
// colTitle
//
this.colTitle.AspectName = "Title";
this.colTitle.Groupable = false;
this.colTitle.Hideable = false;
this.colTitle.Text = "Title";
//
// colUsername
//
this.colUsername.AspectName = "Username";
this.colUsername.Groupable = false;
this.colUsername.Hideable = false;
this.colUsername.Text = "Username";
//
// colDomain
//
this.colDomain.AspectName = "Domain";
this.colDomain.Groupable = false;
this.colDomain.Hideable = false;
this.colDomain.Text = "Domain";
//
// colPassword
//
this.colPassword.AspectName = "Password";
this.colPassword.FillsFreeSpace = true;
this.colPassword.Groupable = false;
this.colPassword.Hideable = false;
this.colPassword.Text = "Password";
//
// lblCredsFound
//
this.lblCredsFound.AutoSize = true;
this.lblCredsFound.Location = new System.Drawing.Point(6, 3);
this.lblCredsFound.Name = "lblCredsFound";
this.lblCredsFound.Size = new System.Drawing.Size(89, 13);
this.lblCredsFound.TabIndex = 3;
this.lblCredsFound.Text = "Credentials found";
//
// btnCredsBack
//
this.btnCredsBack._mice = mRemoteNG.UI.Controls.Base.NGButton.MouseState.HOVER;
this.btnCredsBack.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnCredsBack.Location = new System.Drawing.Point(445, 345);
this.btnCredsBack.Name = "btnCredsBack";
this.btnCredsBack.Size = new System.Drawing.Size(75, 23);
this.btnCredsBack.TabIndex = 2;
this.btnCredsBack.Text = "Back";
this.btnCredsBack.UseVisualStyleBackColor = true;
this.btnCredsBack.Click += new System.EventHandler(this.btnCredsBack_Click);
//
// btnCredsContinue
//
this.btnCredsContinue._mice = mRemoteNG.UI.Controls.Base.NGButton.MouseState.HOVER;
this.btnCredsContinue.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnCredsContinue.Location = new System.Drawing.Point(526, 345);
this.btnCredsContinue.Name = "btnCredsContinue";
this.btnCredsContinue.Size = new System.Drawing.Size(75, 23);
this.btnCredsContinue.TabIndex = 1;
this.btnCredsContinue.Text = "Continue";
this.btnCredsContinue.UseVisualStyleBackColor = true;
this.btnCredsContinue.Click += new System.EventHandler(this.btnCredsContinue_Click);
//
// tabPageSaveRepo
//
this.tabPageSaveRepo.BackColor = System.Drawing.Color.Transparent;
this.tabPageSaveRepo.Controls.Add(this.textBoxConfConPathTab2);
this.tabPageSaveRepo.Controls.Add(this.buttonNewRepoPathBrowse);
this.tabPageSaveRepo.Controls.Add(this.labelWhereToSaveCredFile);
this.tabPageSaveRepo.Controls.Add(this.textBoxCredRepoPath);
this.tabPageSaveRepo.Controls.Add(this.buttonExecuteUpgrade);
this.tabPageSaveRepo.Controls.Add(this.labelSetPassword);
this.tabPageSaveRepo.Controls.Add(this.newRepositoryPasswordEntry);
this.tabPageSaveRepo.Controls.Add(this.labelConfConsPathHeaderOnTab2);
this.tabPageSaveRepo.Controls.Add(this.buttonSaveRepoBack);
this.tabPageSaveRepo.Location = new System.Drawing.Point(4, 24);
this.tabPageSaveRepo.Name = "tabPageSaveRepo";
this.tabPageSaveRepo.Padding = new System.Windows.Forms.Padding(3);
this.tabPageSaveRepo.Size = new System.Drawing.Size(609, 374);
this.tabPageSaveRepo.TabIndex = 1;
this.tabPageSaveRepo.Text = "saveRepoPage";
//
// textBoxConfConPathTab2
//
@@ -266,7 +382,7 @@
this.newRepositoryPasswordEntry.PasswordChar = '\0';
this.newRepositoryPasswordEntry.Size = new System.Drawing.Size(574, 100);
this.newRepositoryPasswordEntry.TabIndex = 3;
this.newRepositoryPasswordEntry.UseSystemPasswordChar = false;
this.newRepositoryPasswordEntry.UseSystemPasswordChar = true;
this.newRepositoryPasswordEntry.Verified += new System.EventHandler(this.newRepositoryPasswordEntry_Verified);
this.newRepositoryPasswordEntry.NotVerified += new System.EventHandler(this.newRepositoryPasswordEntry_NotVerified);
//
@@ -279,17 +395,17 @@
this.labelConfConsPathHeaderOnTab2.TabIndex = 1;
this.labelConfConsPathHeaderOnTab2.Text = "Connections file:";
//
// buttonBack
// buttonSaveRepoBack
//
this.buttonBack._mice = mRemoteNG.UI.Controls.Base.NGButton.MouseState.HOVER;
this.buttonBack.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.buttonBack.Location = new System.Drawing.Point(445, 343);
this.buttonBack.Name = "buttonBack";
this.buttonBack.Size = new System.Drawing.Size(75, 23);
this.buttonBack.TabIndex = 0;
this.buttonBack.Text = "Back";
this.buttonBack.UseVisualStyleBackColor = true;
this.buttonBack.Click += new System.EventHandler(this.buttonBack_Click);
this.buttonSaveRepoBack._mice = mRemoteNG.UI.Controls.Base.NGButton.MouseState.HOVER;
this.buttonSaveRepoBack.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.buttonSaveRepoBack.Location = new System.Drawing.Point(445, 343);
this.buttonSaveRepoBack.Name = "buttonSaveRepoBack";
this.buttonSaveRepoBack.Size = new System.Drawing.Size(75, 23);
this.buttonSaveRepoBack.TabIndex = 0;
this.buttonSaveRepoBack.Text = "Back";
this.buttonSaveRepoBack.UseVisualStyleBackColor = true;
this.buttonSaveRepoBack.Click += new System.EventHandler(this.buttonSaveRepoBack_Click);
//
// CredentialManagerUpgradeForm
//
@@ -308,8 +424,11 @@
this.tabControl.ResumeLayout(false);
this.tabPageWelcome.ResumeLayout(false);
this.tabPageWelcome.PerformLayout();
this.tabPageUpgradeOptions.ResumeLayout(false);
this.tabPageUpgradeOptions.PerformLayout();
this.tabPageHarvestedCreds.ResumeLayout(false);
this.tabPageHarvestedCreds.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.olvFoundCredentials)).EndInit();
this.tabPageSaveRepo.ResumeLayout(false);
this.tabPageSaveRepo.PerformLayout();
this.ResumeLayout(false);
}
@@ -317,14 +436,14 @@
#endregion
private Controls.Base.NGLabel labelDescriptionOfUpgrade;
private Controls.Base.NGButton buttonPerformUpgrade;
private Controls.Base.NGButton buttonBeginUpgrade;
private Controls.Base.NGButton buttonOpenFile;
private Controls.Base.NGButton buttonNewFile;
private Controls.Base.NGButton buttonExit;
private mRemoteNG.UI.Controls.HeadlessTabControl tabControl;
private System.Windows.Forms.TabPage tabPageWelcome;
private System.Windows.Forms.TabPage tabPageUpgradeOptions;
private Controls.Base.NGButton buttonBack;
private System.Windows.Forms.TabPage tabPageSaveRepo;
private Controls.Base.NGButton buttonSaveRepoBack;
private Controls.Base.NGLabel labelConfConsPathHeaderOnTab2;
private Controls.Base.NGButton buttonExecuteUpgrade;
private Controls.Base.NGLabel labelSetPassword;
@@ -337,5 +456,14 @@
private Controls.Base.NGTextBox textBoxConfConPathTab1;
private Controls.Base.NGTextBox textBoxConfConPathTab2;
private System.Windows.Forms.SaveFileDialog newConnectionsFileDialog;
private System.Windows.Forms.TabPage tabPageHarvestedCreds;
private Controls.Base.NGButton btnCredsBack;
private Controls.Base.NGButton btnCredsContinue;
private Controls.Base.NGLabel lblCredsFound;
private Controls.Base.NGListView olvFoundCredentials;
private BrightIdeasSoftware.OLVColumn colUsername;
private BrightIdeasSoftware.OLVColumn colDomain;
private BrightIdeasSoftware.OLVColumn colPassword;
private BrightIdeasSoftware.OLVColumn colTitle;
}
}

View File

@@ -1,12 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security;
using System.Windows.Forms;
using System.Xml.Linq;
using mRemoteNG.App;
using mRemoteNG.Config;
using mRemoteNG.Config.Connections;
using mRemoteNG.Config.DataProviders;
using mRemoteNG.Config.Serializers;
using mRemoteNG.Config.Serializers.Versioning;
using mRemoteNG.Connection;
using mRemoteNG.Credential;
using mRemoteNG.Credential.Repositories;
using mRemoteNG.Security;
using mRemoteNG.Themes;
using mRemoteNG.Tree;
namespace mRemoteNG.UI.Forms
@@ -15,6 +23,10 @@ namespace mRemoteNG.UI.Forms
{
private string _connectionFilePath;
private string _newCredentialRepoPath;
private XDocument _xdoc;
private XmlCredentialManagerUpgrader _upgradingDeserializer;
private ConnectionToCredentialMap _credentialMap;
private readonly ThemeManager _themeManager = ThemeManager.getInstance();
public IDeserializer<string, ConnectionTreeModel> ConnectionDeserializer { get; set; }
public ConnectionsService ConnectionsService { get; set; }
@@ -44,7 +56,10 @@ namespace mRemoteNG.UI.Forms
{
InitializeComponent();
ApplyLanguage();
ApplyTheme();
UpdateUi();
colPassword.AspectGetter =
rowObject => (rowObject as ICredentialRecord)?.Password.ConvertToUnsecureString();
}
private const int CP_NOCLOSE_BUTTON = 0x200;
@@ -60,20 +75,21 @@ namespace mRemoteNG.UI.Forms
public ConnectionTreeModel Deserialize(string serializedData)
{
var xdoc = XDocument.Parse(serializedData);
if (!XmlCredentialManagerUpgrader.CredentialManagerUpgradeNeeded(xdoc))
_xdoc = XDocument.Parse(serializedData);
if (!XmlCredentialManagerUpgrader.CredentialManagerUpgradeNeeded(_xdoc))
return ConnectionDeserializer.Deserialize(serializedData);
// close the splash screen during upgrade
FrmSplashScreen.getInstance().Close();
_upgradingDeserializer = new XmlCredentialManagerUpgrader(ConnectionDeserializer);
var result = ShowDialog();
if (result != DialogResult.OK)
return new ConnectionTreeModel();
var newRepoPassword = newRepositoryPasswordEntry.SecureString;
var upgradingDeserializer = new XmlCredentialManagerUpgrader(CredentialService, NewCredentialRepoPath, ConnectionDeserializer, newRepoPassword);
var connectionTreeModel = upgradingDeserializer.Deserialize(serializedData);
SaveCredentialsToNewRepository(_credentialMap.DistinctCredentialRecords, newRepoPassword, _newCredentialRepoPath);
var connectionTreeModel = _upgradingDeserializer.Deserialize(serializedData, _credentialMap);
ConnectionsService.ConnectionsLoaded += ConnectionsServiceOnConnectionsLoaded;
@@ -91,23 +107,39 @@ namespace mRemoteNG.UI.Forms
private void ApplyLanguage()
{
// tab 1
// Welcome tab
labelDescriptionOfUpgrade.Text = Language.strCredentialManagerUpgradeDescription;
labelConfConsPathHeaderOnTab1.Text = $@"{Language.strConnectionFilePath}:";
buttonPerformUpgrade.Text = Language.strUpgrade;
buttonBeginUpgrade.Text = Language.strUpgrade;
buttonOpenFile.Text = Language.strOpenADifferentFile;
buttonNewFile.Text = Language.strCreateAndOpenNewFile;
buttonExit.Text = Language.strMenuExit;
// tab 2
// HarvestedCreds tab
lblCredsFound.Text = "Credentials found";
colTitle.Text = Language.strPropertyNameName;
colUsername.Text = Language.strPropertyNameUsername;
colDomain.Text = Language.strPropertyNameDomain;
colPassword.Text = Language.strPropertyNamePassword;
// SaveRepo tab
labelConfConsPathHeaderOnTab2.Text = $@"{Language.strConnectionFilePath}:";
labelWhereToSaveCredFile.Text = "Where should we save the new credential file?";
labelSetPassword.Text = "Set password for the credential repository";
buttonNewRepoPathBrowse.Text = Language.strButtonBrowse;
buttonBack.Text = Language.strBack;
buttonSaveRepoBack.Text = Language.strBack;
buttonExecuteUpgrade.Text = Language.strUpgrade;
}
private void ApplyTheme()
{
if (!_themeManager.ThemingActive)
return;
BackColor = _themeManager.ActiveTheme.ExtendedPalette.getColor("Dialog_Background");
ForeColor = _themeManager.ActiveTheme.ExtendedPalette.getColor("Dialog_Foreground");
}
private void UpdateUi()
{
textBoxConfConPathTab1.Text = ConnectionFilePath;
@@ -115,17 +147,25 @@ namespace mRemoteNG.UI.Forms
textBoxCredRepoPath.Text = NewCredentialRepoPath;
}
private void buttonPerformUpgrade_Click(object sender, EventArgs e)
#region WelcomePage
private void buttonBeginUpgrade_Click(object sender, EventArgs e)
{
tabControl.SelectedTab = tabPageUpgradeOptions;
tabControl.SelectedTab = tabPageHarvestedCreds;
// harvest creds and update olv
_credentialMap = _upgradingDeserializer.UpgradeUserFilesForCredentialManager(_xdoc);
olvFoundCredentials.SetObjects(_credentialMap.DistinctCredentialRecords);
olvFoundCredentials.AutoResizeColumns();
}
private void buttonOpenFile_Click(object sender, EventArgs e)
{
var loadConnectionsDialog = DialogFactory.BuildLoadConnectionsDialog();
var dialogResult = loadConnectionsDialog.ShowDialog(this);
if (dialogResult == DialogResult.OK)
ConnectionFilePath = loadConnectionsDialog.FileName;
if (dialogResult != DialogResult.OK)
return;
ConnectionFilePath = loadConnectionsDialog.FileName;
}
private void buttonNewFile_Click(object sender, EventArgs e)
@@ -140,7 +180,22 @@ namespace mRemoteNG.UI.Forms
{
Shutdown.Quit();
}
#endregion
#region HarvestedCredsPage
private void btnCredsBack_Click(object sender, EventArgs e)
{
tabControl.SelectedTab = tabPageWelcome;
}
private void btnCredsContinue_Click(object sender, EventArgs e)
{
tabControl.SelectedTab = tabPageSaveRepo;
}
#endregion
#region SaveRepoPage
private void buttonNewRepoPathBrowse_Click(object sender, EventArgs e)
{
var dialogResult = newCredRepoPathDialog.ShowDialog(this);
@@ -148,20 +203,9 @@ namespace mRemoteNG.UI.Forms
NewCredentialRepoPath = newCredRepoPathDialog.FileName;
}
private void buttonBack_Click(object sender, EventArgs e)
private void buttonSaveRepoBack_Click(object sender, EventArgs e)
{
tabControl.SelectedTab = tabPageWelcome;
}
/// <summary>
/// Validate field entries to determine if we have enough information to perform the upgrade
/// </summary>
private void ValidateFields()
{
buttonExecuteUpgrade.Enabled =
newRepositoryPasswordEntry.PasswordsMatch &&
newRepositoryPasswordEntry.SecureString.Length > 0 &&
!string.IsNullOrWhiteSpace(textBoxCredRepoPath.Text);
tabControl.SelectedTab = tabPageHarvestedCreds;
}
private void textBoxCredRepoPath_TextChanged(object sender, EventArgs e)
@@ -178,5 +222,55 @@ namespace mRemoteNG.UI.Forms
{
ValidateFields();
}
/// <summary>
/// Validate field entries to determine if we have enough information to perform the upgrade
/// </summary>
private void ValidateFields()
{
buttonExecuteUpgrade.Enabled =
newRepositoryPasswordEntry.PasswordsMatch &&
newRepositoryPasswordEntry.SecureString.Length > 0 &&
!string.IsNullOrWhiteSpace(textBoxCredRepoPath.Text);
}
#endregion
private void SaveCredentialsToNewRepository(
IEnumerable<ICredentialRecord> harvestedCredentials,
SecureString newRepoPassword,
string repoPath)
{
var newCredentialRepository = BuildXmlCredentialRepo(newRepoPassword, repoPath);
AddHarvestedCredentialsToRepo(harvestedCredentials, newCredentialRepository);
newCredentialRepository.SaveCredentials(newRepoPassword);
CredentialService.AddRepository(newCredentialRepository);
}
private ICredentialRepository BuildXmlCredentialRepo(SecureString newCredRepoKey, string repoPath)
{
var repositoryConfig = new CredentialRepositoryConfig
{
Source = repoPath,
Title = "Converted Credentials",
TypeName = "Xml",
Key = newCredRepoKey
};
var xmlRepoFactory = CredentialService.GetRepositoryFactoryForConfig(repositoryConfig);
if (!xmlRepoFactory.Any())
throw new CredentialRepositoryTypeNotSupportedException(repositoryConfig.TypeName);
var newRepo = xmlRepoFactory.First().Build(repositoryConfig, true);
return newRepo;
}
private void AddHarvestedCredentialsToRepo(IEnumerable<ICredentialRecord> harvestedCredentials, ICredentialRepository repo)
{
foreach (var credential in harvestedCredentials)
repo.CredentialRecords.Add(credential);
}
}
}

View File

@@ -151,6 +151,7 @@
<Compile Include="Config\CredentialRecordLoader.cs" />
<Compile Include="Config\CredentialRecordSaver.cs" />
<Compile Include="Config\CredentialRepositoryListPersistor.cs" />
<Compile Include="Config\ConnectionToCredentialMap.cs" />
<Compile Include="Config\DatabaseConnectors\ConnectionTestResult.cs" />
<Compile Include="Config\DatabaseConnectors\DatabaseConnectorFactory.cs" />
<Compile Include="Config\DatabaseConnectors\SqlDatabaseConnectionTester.cs" />