diff --git a/mRemoteV1/Config/CredentialRecordLoader.cs b/mRemoteV1/Config/CredentialRecordLoader.cs index bd7d879a..7d9aafa8 100644 --- a/mRemoteV1/Config/CredentialRecordLoader.cs +++ b/mRemoteV1/Config/CredentialRecordLoader.cs @@ -24,10 +24,10 @@ namespace mRemoteNG.Config _deserializer = deserializer; } - public IEnumerable Load(SecureString decryptionKey) + public IEnumerable Load(SecureString key) { var serializedCredentials = _dataProvider.Load(); - return _deserializer.Deserialize(serializedCredentials, decryptionKey); + return _deserializer.Deserialize(serializedCredentials, key); } } } \ No newline at end of file diff --git a/mRemoteV1/Credential/CredentialRepositoryConfig.cs b/mRemoteV1/Credential/CredentialRepositoryConfig.cs new file mode 100644 index 00000000..db49c671 --- /dev/null +++ b/mRemoteV1/Credential/CredentialRepositoryConfig.cs @@ -0,0 +1,14 @@ +using System; +using System.Security; +using mRemoteNG.Credential.Repositories; + +namespace mRemoteNG.Credential +{ + public class CredentialRepositoryConfig : ICredentialRepositoryConfig + { + public Guid Id { get; } = Guid.NewGuid(); + public string Name { get; } = ""; + public string Source { get; set; } = ""; + public SecureString Key { get; set; } = new SecureString(); + } +} \ No newline at end of file diff --git a/mRemoteV1/Credential/Repositories/XmlCredentialRepository.cs b/mRemoteV1/Credential/Repositories/XmlCredentialRepository.cs new file mode 100644 index 00000000..4a84c1c1 --- /dev/null +++ b/mRemoteV1/Credential/Repositories/XmlCredentialRepository.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Security; +using mRemoteNG.Config.DataProviders; +using mRemoteNG.Config.Serializers; + +namespace mRemoteNG.Credential.Repositories +{ + public class XmlCredentialRepository : ICredentialRepository + { + private readonly IDataProvider _dataProvider; + private readonly XmlCredentialDeserializer _deserializer; + + public ICredentialRepositoryConfig Config { get; } = new CredentialRepositoryConfig(); + + public XmlCredentialRepository(IDataProvider dataProvider, XmlCredentialDeserializer deserializer) + { + if (dataProvider == null) + throw new ArgumentNullException(nameof(dataProvider)); + if (deserializer == null) + throw new ArgumentNullException(nameof(deserializer)); + + _dataProvider = dataProvider; + _deserializer = deserializer; + } + + + + public IEnumerable LoadCredentials(SecureString decryptionKey) + { + var serializedCredentials = _dataProvider.Load(); + return _deserializer.Deserialize(serializedCredentials, decryptionKey); + } + } +} \ No newline at end of file diff --git a/mRemoteV1/UI/Controls/ISelectionTarget.cs b/mRemoteV1/UI/Controls/ISelectionTarget.cs index fe83ca92..bb6ad6fc 100644 --- a/mRemoteV1/UI/Controls/ISelectionTarget.cs +++ b/mRemoteV1/UI/Controls/ISelectionTarget.cs @@ -1,5 +1,4 @@ using System.Drawing; -using mRemoteNG.Credential; namespace mRemoteNG.UI.Controls { @@ -7,6 +6,6 @@ namespace mRemoteNG.UI.Controls { string Text { get; set; } Image Image { get; } - IFactory Factory { get; } + T Config { get; } } } \ No newline at end of file diff --git a/mRemoteV1/UI/Forms/CredentialManagerPages/CredentialRepositoryEditorPages/CredentialRepositoryPageEditorFactory.cs b/mRemoteV1/UI/Forms/CredentialManagerPages/CredentialRepositoryEditorPages/CredentialRepositoryPageEditorFactory.cs new file mode 100644 index 00000000..6cf9a81d --- /dev/null +++ b/mRemoteV1/UI/Forms/CredentialManagerPages/CredentialRepositoryEditorPages/CredentialRepositoryPageEditorFactory.cs @@ -0,0 +1,13 @@ +using System.Windows.Forms; +using mRemoteNG.Credential.Repositories; + +namespace mRemoteNG.UI.Forms.CredentialManagerPages.CredentialRepositoryEditorPages +{ + public class CredentialRepositoryPageEditorFactory + { + public static Control BuildXmlCredentialRepositoryEditorPage(T config, Control previousPage) where T : ICredentialRepositoryConfig + { + return new XmlCredentialRepositoryEditorPage(config, previousPage); + } + } +} \ No newline at end of file diff --git a/mRemoteV1/UI/Forms/CredentialManagerPages/CredentialRepositoryEditorPages/XmlCredentialRepositoryEditorPage.Designer.cs b/mRemoteV1/UI/Forms/CredentialManagerPages/CredentialRepositoryEditorPages/XmlCredentialRepositoryEditorPage.Designer.cs new file mode 100644 index 00000000..9d7949d5 --- /dev/null +++ b/mRemoteV1/UI/Forms/CredentialManagerPages/CredentialRepositoryEditorPages/XmlCredentialRepositoryEditorPage.Designer.cs @@ -0,0 +1,200 @@ +namespace mRemoteNG.UI.Forms.CredentialManagerPages.CredentialRepositoryEditorPages +{ + partial class XmlCredentialRepositoryEditorPage + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.labelPageTitle = new System.Windows.Forms.Label(); + this.buttonBrowseFiles = new System.Windows.Forms.Button(); + this.labelFilePath = new System.Windows.Forms.Label(); + this.textBoxFilePath = new System.Windows.Forms.TextBox(); + this.selectFilePathDialog = new System.Windows.Forms.SaveFileDialog(); + this.label1 = new System.Windows.Forms.Label(); + this.txtboxPassword = new mRemoteNG.UI.Controls.SecureTextBox(); + this.txtboxPasswordVerify = new mRemoteNG.UI.Controls.SecureTextBox(); + this.labelVerifyPassword = new System.Windows.Forms.Label(); + this.buttonConfirm = new System.Windows.Forms.Button(); + this.txtboxId = new System.Windows.Forms.TextBox(); + this.labelId = new System.Windows.Forms.Label(); + this.buttonBack = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // labelPageTitle + // + this.labelPageTitle.AutoSize = true; + this.labelPageTitle.Location = new System.Drawing.Point(4, 4); + this.labelPageTitle.Name = "labelPageTitle"; + this.labelPageTitle.Size = new System.Drawing.Size(132, 13); + this.labelPageTitle.TabIndex = 0; + this.labelPageTitle.Text = "XML Credential Repository"; + // + // buttonBrowseFiles + // + this.buttonBrowseFiles.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.buttonBrowseFiles.Location = new System.Drawing.Point(222, 121); + this.buttonBrowseFiles.Name = "buttonBrowseFiles"; + this.buttonBrowseFiles.Size = new System.Drawing.Size(75, 23); + this.buttonBrowseFiles.TabIndex = 1; + this.buttonBrowseFiles.Text = "Browse"; + this.buttonBrowseFiles.UseVisualStyleBackColor = true; + this.buttonBrowseFiles.Click += new System.EventHandler(this.buttonBrowseFiles_Click); + // + // labelFilePath + // + this.labelFilePath.AutoSize = true; + this.labelFilePath.Location = new System.Drawing.Point(4, 84); + this.labelFilePath.Name = "labelFilePath"; + this.labelFilePath.Size = new System.Drawing.Size(48, 13); + this.labelFilePath.TabIndex = 2; + this.labelFilePath.Text = "File Path"; + // + // textBoxFilePath + // + this.textBoxFilePath.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.textBoxFilePath.Location = new System.Drawing.Point(7, 100); + this.textBoxFilePath.Name = "textBoxFilePath"; + this.textBoxFilePath.Size = new System.Drawing.Size(290, 20); + this.textBoxFilePath.TabIndex = 3; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(4, 147); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(123, 13); + this.label1.TabIndex = 5; + this.label1.Text = "Set encryption password"; + // + // txtboxPassword + // + this.txtboxPassword.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtboxPassword.Location = new System.Drawing.Point(7, 163); + this.txtboxPassword.Name = "txtboxPassword"; + this.txtboxPassword.Size = new System.Drawing.Size(290, 20); + this.txtboxPassword.TabIndex = 6; + // + // txtboxPasswordVerify + // + this.txtboxPasswordVerify.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtboxPasswordVerify.Location = new System.Drawing.Point(7, 202); + this.txtboxPasswordVerify.Name = "txtboxPasswordVerify"; + this.txtboxPasswordVerify.Size = new System.Drawing.Size(290, 20); + this.txtboxPasswordVerify.TabIndex = 7; + // + // labelVerifyPassword + // + this.labelVerifyPassword.AutoSize = true; + this.labelVerifyPassword.Location = new System.Drawing.Point(4, 186); + this.labelVerifyPassword.Name = "labelVerifyPassword"; + this.labelVerifyPassword.Size = new System.Drawing.Size(81, 13); + this.labelVerifyPassword.TabIndex = 8; + this.labelVerifyPassword.Text = "Verify password"; + // + // buttonConfirm + // + this.buttonConfirm.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.buttonConfirm.Location = new System.Drawing.Point(141, 234); + this.buttonConfirm.Name = "buttonConfirm"; + this.buttonConfirm.Size = new System.Drawing.Size(75, 23); + this.buttonConfirm.TabIndex = 9; + this.buttonConfirm.Text = "Confirm"; + this.buttonConfirm.UseVisualStyleBackColor = true; + this.buttonConfirm.Click += new System.EventHandler(this.buttonConfirm_Click); + // + // txtboxId + // + this.txtboxId.Location = new System.Drawing.Point(7, 49); + this.txtboxId.Name = "txtboxId"; + this.txtboxId.ReadOnly = true; + this.txtboxId.Size = new System.Drawing.Size(212, 20); + this.txtboxId.TabIndex = 10; + this.txtboxId.TabStop = false; + // + // labelId + // + this.labelId.AutoSize = true; + this.labelId.Location = new System.Drawing.Point(4, 33); + this.labelId.Name = "labelId"; + this.labelId.Size = new System.Drawing.Size(18, 13); + this.labelId.TabIndex = 11; + this.labelId.Text = "ID"; + // + // buttonBack + // + this.buttonBack.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.buttonBack.Location = new System.Drawing.Point(222, 234); + this.buttonBack.Name = "buttonBack"; + this.buttonBack.Size = new System.Drawing.Size(75, 23); + this.buttonBack.TabIndex = 12; + this.buttonBack.Text = "Back"; + this.buttonBack.UseVisualStyleBackColor = true; + this.buttonBack.Click += new System.EventHandler(this.buttonBack_Click); + // + // XmlCredentialRepositoryEditorPage + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.buttonBack); + this.Controls.Add(this.labelId); + this.Controls.Add(this.txtboxId); + this.Controls.Add(this.buttonConfirm); + this.Controls.Add(this.labelVerifyPassword); + this.Controls.Add(this.txtboxPasswordVerify); + this.Controls.Add(this.txtboxPassword); + this.Controls.Add(this.label1); + this.Controls.Add(this.textBoxFilePath); + this.Controls.Add(this.labelFilePath); + this.Controls.Add(this.buttonBrowseFiles); + this.Controls.Add(this.labelPageTitle); + this.MinimumSize = new System.Drawing.Size(300, 260); + this.Name = "XmlCredentialRepositoryEditorPage"; + this.Size = new System.Drawing.Size(300, 260); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label labelPageTitle; + private System.Windows.Forms.Button buttonBrowseFiles; + private System.Windows.Forms.Label labelFilePath; + private System.Windows.Forms.TextBox textBoxFilePath; + private System.Windows.Forms.SaveFileDialog selectFilePathDialog; + private System.Windows.Forms.Label label1; + private Controls.SecureTextBox txtboxPassword; + private Controls.SecureTextBox txtboxPasswordVerify; + private System.Windows.Forms.Label labelVerifyPassword; + private System.Windows.Forms.Button buttonConfirm; + private System.Windows.Forms.TextBox txtboxId; + private System.Windows.Forms.Label labelId; + private System.Windows.Forms.Button buttonBack; + } +} diff --git a/mRemoteV1/UI/Forms/CredentialManagerPages/CredentialRepositoryEditorPages/XmlCredentialRepositoryEditorPage.cs b/mRemoteV1/UI/Forms/CredentialManagerPages/CredentialRepositoryEditorPages/XmlCredentialRepositoryEditorPage.cs new file mode 100644 index 00000000..57137dbf --- /dev/null +++ b/mRemoteV1/UI/Forms/CredentialManagerPages/CredentialRepositoryEditorPages/XmlCredentialRepositoryEditorPage.cs @@ -0,0 +1,46 @@ +using System; +using System.Windows.Forms; +using mRemoteNG.Credential.Repositories; + +namespace mRemoteNG.UI.Forms.CredentialManagerPages.CredentialRepositoryEditorPages +{ + public partial class XmlCredentialRepositoryEditorPage : UserControl + { + private readonly ICredentialRepositoryConfig _repositoryConfig; + private readonly Control _previousPage; + + public XmlCredentialRepositoryEditorPage(ICredentialRepositoryConfig repositoryConfig, Control previousPage) + { + if (repositoryConfig == null) + throw new ArgumentNullException(nameof(repositoryConfig)); + + _repositoryConfig = repositoryConfig; + _previousPage = previousPage; + InitializeComponent(); + PopulateFields(); + } + + private void PopulateFields() + { + txtboxId.Text = _repositoryConfig.Id.ToString(); + textBoxFilePath.Text = _repositoryConfig.Source; + } + + private void buttonBrowseFiles_Click(object sender, EventArgs e) + { + selectFilePathDialog.ShowDialog(this); + } + + private void buttonConfirm_Click(object sender, EventArgs e) + { + + } + + private void buttonBack_Click(object sender, EventArgs e) + { + var parent = Parent; + parent.Controls.Clear(); + parent.Controls.Add(_previousPage); + } + } +} \ No newline at end of file diff --git a/mRemoteV1/UI/Forms/CredentialManagerPages/CredentialRepositoryEditorPages/XmlCredentialRepositoryEditorPage.resx b/mRemoteV1/UI/Forms/CredentialManagerPages/CredentialRepositoryEditorPages/XmlCredentialRepositoryEditorPage.resx new file mode 100644 index 00000000..e60a0f88 --- /dev/null +++ b/mRemoteV1/UI/Forms/CredentialManagerPages/CredentialRepositoryEditorPages/XmlCredentialRepositoryEditorPage.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/mRemoteV1/UI/Forms/CredentialManagerPages/CredentialRepositorySelectionPage.Designer.cs b/mRemoteV1/UI/Forms/CredentialManagerPages/CredentialRepositorySelectionPage.Designer.cs index 1191355a..b4ffef7f 100644 --- a/mRemoteV1/UI/Forms/CredentialManagerPages/CredentialRepositorySelectionPage.Designer.cs +++ b/mRemoteV1/UI/Forms/CredentialManagerPages/CredentialRepositorySelectionPage.Designer.cs @@ -46,6 +46,7 @@ this.buttonContinue.TabIndex = 4; this.buttonContinue.Text = "Continue"; this.buttonContinue.UseVisualStyleBackColor = true; + this.buttonContinue.Click += new System.EventHandler(this.buttonContinue_Click); // // objectListView // diff --git a/mRemoteV1/UI/Forms/CredentialManagerPages/CredentialRepositorySelectionPage.cs b/mRemoteV1/UI/Forms/CredentialManagerPages/CredentialRepositorySelectionPage.cs index 9d363687..71ccab70 100644 --- a/mRemoteV1/UI/Forms/CredentialManagerPages/CredentialRepositorySelectionPage.cs +++ b/mRemoteV1/UI/Forms/CredentialManagerPages/CredentialRepositorySelectionPage.cs @@ -1,8 +1,10 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Drawing; using System.Windows.Forms; -using mRemoteNG.Credential; +using mRemoteNG.Credential.Repositories; using mRemoteNG.UI.Controls; +using mRemoteNG.UI.Forms.CredentialManagerPages.CredentialRepositoryEditorPages; namespace mRemoteNG.UI.Forms.CredentialManagerPages { @@ -11,13 +13,13 @@ namespace mRemoteNG.UI.Forms.CredentialManagerPages public string PageName { get; } = "add repo"; public Image PageIcon { get; } - public CredentialRepositorySelectionPage(IEnumerable> selectionTargets) + public CredentialRepositorySelectionPage(IEnumerable> selectionTargets) { InitializeComponent(); SetupListView(selectionTargets); } - private void SetupListView(IEnumerable> selectionTargets) + private void SetupListView(IEnumerable> selectionTargets) { olvColumnName.ImageGetter = ImageGetter; objectListView.SetObjects(selectionTargets); @@ -25,12 +27,23 @@ namespace mRemoteNG.UI.Forms.CredentialManagerPages private object ImageGetter(object rowObject) { - var selection = rowObject as ISelectionTarget; + var selection = rowObject as ISelectionTarget; if (selection == null) return ""; var imgHash = selection.Image.GetHashCode().ToString(); if (!objectListView.LargeImageList.Images.ContainsKey(imgHash)) objectListView.LargeImageList.Images.Add(imgHash, selection.Image); return imgHash; } + + private void buttonContinue_Click(object sender, EventArgs e) + { + var selection = objectListView.SelectedObject as ISelectionTarget; + if (selection == null) return; + var editorPage = CredentialRepositoryPageEditorFactory.BuildXmlCredentialRepositoryEditorPage(selection.Config, this); + editorPage.Dock = DockStyle.Fill; + var parent = Parent; + parent.Controls.Clear(); + parent.Controls.Add(editorPage); + } } } \ No newline at end of file diff --git a/mRemoteV1/UI/Forms/CredentialManagerPages/CredentialRepositorySelectors/KeePassRepositorySelector.cs b/mRemoteV1/UI/Forms/CredentialManagerPages/CredentialRepositorySelectors/KeePassRepositorySelector.cs index 185d4c0d..93123063 100644 --- a/mRemoteV1/UI/Forms/CredentialManagerPages/CredentialRepositorySelectors/KeePassRepositorySelector.cs +++ b/mRemoteV1/UI/Forms/CredentialManagerPages/CredentialRepositorySelectors/KeePassRepositorySelector.cs @@ -1,13 +1,14 @@ using System.Drawing; using mRemoteNG.Credential; +using mRemoteNG.Credential.Repositories; using mRemoteNG.UI.Controls; namespace mRemoteNG.UI.Forms.CredentialManagerPages.CredentialRepositorySelectors { - public class KeePassRepositorySelector : ISelectionTarget + public class KeePassRepositorySelector : ISelectionTarget { public string Text { get; set; } = "KeePass"; public Image Image { get; } = Resources.keepass_32x32; - public IFactory Factory { get; } + public ICredentialRepositoryConfig Config { get; } = new CredentialRepositoryConfig(); } } \ No newline at end of file diff --git a/mRemoteV1/UI/Forms/CredentialManagerPages/CredentialRepositorySelectors/XmlCredentialRepositorySelector.cs b/mRemoteV1/UI/Forms/CredentialManagerPages/CredentialRepositorySelectors/XmlCredentialRepositorySelector.cs index eca8489e..5783fe48 100644 --- a/mRemoteV1/UI/Forms/CredentialManagerPages/CredentialRepositorySelectors/XmlCredentialRepositorySelector.cs +++ b/mRemoteV1/UI/Forms/CredentialManagerPages/CredentialRepositorySelectors/XmlCredentialRepositorySelector.cs @@ -1,13 +1,14 @@ using System.Drawing; using mRemoteNG.Credential; +using mRemoteNG.Credential.Repositories; using mRemoteNG.UI.Controls; namespace mRemoteNG.UI.Forms.CredentialManagerPages.CredentialRepositorySelectors { - public class XmlCredentialRepositorySelector : ISelectionTarget + public class XmlCredentialRepositorySelector : ISelectionTarget { public string Text { get; set; } = "XML"; public Image Image { get; } = Resources.xml; - public IFactory Factory { get; } + public ICredentialRepositoryConfig Config { get; } = new CredentialRepositoryConfig(); } } \ No newline at end of file diff --git a/mRemoteV1/UI/Menu/ToolsMenu.cs b/mRemoteV1/UI/Menu/ToolsMenu.cs index 32f389f9..91954edb 100644 --- a/mRemoteV1/UI/Menu/ToolsMenu.cs +++ b/mRemoteV1/UI/Menu/ToolsMenu.cs @@ -2,6 +2,7 @@ using System.Windows.Forms; using mRemoteNG.App; using mRemoteNG.Credential; +using mRemoteNG.Credential.Repositories; using mRemoteNG.UI.Controls; using mRemoteNG.UI.Forms; using mRemoteNG.UI.Forms.CredentialManagerPages; @@ -129,7 +130,7 @@ namespace mRemoteNG.UI.Menu DeletionConfirmer = new CredentialDeletionMsgBoxConfirmer(MessageBox.Show) }, new CredentialSourcesPage(new CredentialProviderCatalog()), - new CredentialRepositorySelectionPage(new ISelectionTarget[] + new CredentialRepositorySelectionPage(new ISelectionTarget[] { new XmlCredentialRepositorySelector(), new KeePassRepositorySelector() diff --git a/mRemoteV1/mRemoteV1.csproj b/mRemoteV1/mRemoteV1.csproj index 2844f07e..83a3c125 100644 --- a/mRemoteV1/mRemoteV1.csproj +++ b/mRemoteV1/mRemoteV1.csproj @@ -222,6 +222,7 @@ + @@ -356,6 +357,13 @@ CredentialListPage.cs + + + UserControl + + + XmlCredentialRepositoryEditorPage.cs + UserControl @@ -651,6 +659,9 @@ CredentialListPage.cs + + XmlCredentialRepositoryEditorPage.cs + CredentialRepositorySelectionPage.cs