diff --git a/mRemoteNG/Config/Settings/Registry/CommonRegistrySettings.cs b/mRemoteNG/Config/Settings/Registry/CommonRegistrySettings.cs
index 7174d9aa..bdc74eb2 100644
--- a/mRemoteNG/Config/Settings/Registry/CommonRegistrySettings.cs
+++ b/mRemoteNG/Config/Settings/Registry/CommonRegistrySettings.cs
@@ -40,22 +40,22 @@ namespace mRemoteNG.Config.Settings.Registry
#region general credential registry settings
///
- /// Setting that indicates whether exporting passwords is allowed.
+ /// Specifies whether the export of passwords for saved connections is allowed.
///
public static bool AllowExportPasswords { get; }
///
- /// Setting that indicates whether exporting usernames is allowed.
+ /// Specifies whether the export of usernames for saved connections is allowed.
///
public static bool AllowExportUsernames { get; }
///
- /// Setting that indicates whether saving passwords in connections is allowed.
+ /// Specifies whether the saving of usernames for saved connections is allowed.
///
public static bool AllowSavePasswords { get; }
///
- /// Setting that indicates whether saving in connections usernames is allowed.
+ /// Specifies whether the saving of passwords for saved connections is allowed.
///
public static bool AllowSaveUsernames { get; }
diff --git a/mRemoteNG/Config/Settings/Registry/OptRegistrySecurityPage.cs b/mRemoteNG/Config/Settings/Registry/OptRegistrySecurityPage.cs
new file mode 100644
index 00000000..d0b64289
--- /dev/null
+++ b/mRemoteNG/Config/Settings/Registry/OptRegistrySecurityPage.cs
@@ -0,0 +1,103 @@
+using System.Runtime.Versioning;
+using Microsoft.Win32;
+using mRemoteNG.App.Info;
+using mRemoteNG.Security;
+using mRemoteNG.Tools.WindowsRegistry;
+
+namespace mRemoteNG.Config.Settings.Registry
+{
+ [SupportedOSPlatform("windows")]
+ public sealed partial class OptRegistrySecurityPage
+ {
+ ///
+ /// Specifies whether the complete connections file is encrypted.
+ ///
+ public WinRegistryEntry EncryptCompleteConnectionsFile { get; private set; }
+
+ ///
+ /// Specifies the encryption engine used for encryption.
+ ///
+ public WinRegistryEntry EncryptionEngine { get; private set; }
+
+ ///
+ /// Specifies the block cipher mode used for encryption.
+ ///
+ public WinRegistryEntry EncryptionBlockCipherMode { get; private set; }
+
+ ///
+ /// Specifies the number of iterations used in the encryption key derivation process.
+ ///
+ public WinRegistryEntry EncryptionKeyDerivationIterations { get; private set; }
+
+ public OptRegistrySecurityPage()
+ {
+
+ RegistryHive hive = WindowsRegistryInfo.Hive;
+ string subKey = WindowsRegistryInfo.SecurityOptions;
+
+ EncryptCompleteConnectionsFile = new WinRegistryEntry(hive, subKey, nameof(EncryptCompleteConnectionsFile)).Read();
+ EncryptionEngine = new WinRegistryEntry(hive, subKey, nameof(EncryptionEngine)).Read();
+ EncryptionBlockCipherMode = new WinRegistryEntry(hive, subKey, nameof(EncryptionBlockCipherMode)).Read();
+ EncryptionKeyDerivationIterations = new WinRegistryEntry(hive, subKey, nameof(EncryptionKeyDerivationIterations)).Read();
+
+ SetupValidation();
+ Apply();
+ }
+
+ ///
+ /// Configures validation settings for various parameters
+ ///
+ private void SetupValidation()
+ {
+ var SecurityPage = new UI.Forms.OptionsPages.SecurityPage();
+
+ EncryptionEngine.SetValidation();
+ EncryptionBlockCipherMode.SetValidation();
+
+ int EncryptionKeyDerivIteraMin = (int)SecurityPage.numberBoxKdfIterations.Minimum;
+ int EncryptionKeyDerivIteraMax = (int)SecurityPage.numberBoxKdfIterations.Maximum;
+ EncryptionKeyDerivationIterations.SetValidation(EncryptionKeyDerivIteraMin, EncryptionKeyDerivIteraMax);
+ }
+
+ ///
+ /// Applies registry settings and overrides various properties.
+ ///
+ private void Apply()
+ {
+ ApplyEncryptCompleteConnectionsFile();
+ ApplyEncryptionEngine();
+ ApplyEncryptionBlockCipherMode();
+ ApplyEncryptionKeyDerivationIterations();
+ }
+
+ private void ApplyEncryptCompleteConnectionsFile()
+ {
+ if (EncryptCompleteConnectionsFile.IsSet)
+ Properties.OptionsSecurityPage.Default.EncryptCompleteConnectionsFile = EncryptCompleteConnectionsFile.Value;
+ }
+
+ private void ApplyEncryptionEngine()
+ {
+ if (EncryptionEngine.IsValid)
+ {
+ BlockCipherEngines blockCipherEngines = (BlockCipherEngines)System.Enum.Parse(typeof(BlockCipherEngines), EncryptionEngine.Value);
+ Properties.OptionsSecurityPage.Default.EncryptionEngine = blockCipherEngines;
+ }
+ }
+
+ private void ApplyEncryptionBlockCipherMode()
+ {
+ if (EncryptionBlockCipherMode.IsValid)
+ {
+ BlockCipherModes blockCipherModes = (BlockCipherModes)System.Enum.Parse(typeof(BlockCipherModes), EncryptionBlockCipherMode.Value);
+ Properties.OptionsSecurityPage.Default.EncryptionBlockCipherMode = blockCipherModes;
+ }
+ }
+
+ private void ApplyEncryptionKeyDerivationIterations()
+ {
+ if (EncryptionKeyDerivationIterations.IsValid)
+ Properties.OptionsSecurityPage.Default.EncryptionKeyDerivationIterations = EncryptionKeyDerivationIterations.Value;
+ }
+ }
+}
\ No newline at end of file
diff --git a/mRemoteNG/UI/Forms/OptionsPages/SecurityPage.Designer.cs b/mRemoteNG/UI/Forms/OptionsPages/SecurityPage.Designer.cs
index 87765b46..5280b1db 100644
--- a/mRemoteNG/UI/Forms/OptionsPages/SecurityPage.Designer.cs
+++ b/mRemoteNG/UI/Forms/OptionsPages/SecurityPage.Designer.cs
@@ -40,20 +40,32 @@ namespace mRemoteNG.UI.Forms.OptionsPages
labelKdfIterations = new MrngLabel();
numberBoxKdfIterations = new MrngNumericUpDown();
btnTestSettings = new MrngButton();
+ lblRegistrySettingsUsedInfo = new System.Windows.Forms.Label();
+ pnlOptions = new System.Windows.Forms.Panel();
+ groupPasswordGenerator = new System.Windows.Forms.GroupBox();
+ pnlPasswordTxtAndBtn = new System.Windows.Forms.TableLayoutPanel();
+ txtPasswdGenerator = new System.Windows.Forms.TextBox();
+ btnPasswdGenerator = new System.Windows.Forms.Button();
+ lblPasswdGenDescription = new System.Windows.Forms.Label();
groupAdvancedSecurityOptions.SuspendLayout();
tableLayoutPanel1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)numberBoxKdfIterations).BeginInit();
+ pnlOptions.SuspendLayout();
+ groupPasswordGenerator.SuspendLayout();
+ pnlPasswordTxtAndBtn.SuspendLayout();
SuspendLayout();
//
// chkEncryptCompleteFile
//
chkEncryptCompleteFile._mice = MrngCheckBox.MouseState.OUT;
chkEncryptCompleteFile.AutoSize = true;
+ chkEncryptCompleteFile.Dock = System.Windows.Forms.DockStyle.Top;
chkEncryptCompleteFile.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
- chkEncryptCompleteFile.Location = new System.Drawing.Point(12, 10);
+ chkEncryptCompleteFile.Location = new System.Drawing.Point(0, 0);
chkEncryptCompleteFile.Margin = new System.Windows.Forms.Padding(6);
chkEncryptCompleteFile.Name = "chkEncryptCompleteFile";
- chkEncryptCompleteFile.Size = new System.Drawing.Size(286, 27);
+ chkEncryptCompleteFile.Padding = new System.Windows.Forms.Padding(4);
+ chkEncryptCompleteFile.Size = new System.Drawing.Size(610, 25);
chkEncryptCompleteFile.TabIndex = 0;
chkEncryptCompleteFile.Text = "Encrypt complete connection file";
chkEncryptCompleteFile.UseVisualStyleBackColor = true;
@@ -64,10 +76,10 @@ namespace mRemoteNG.UI.Forms.OptionsPages
comboBoxEncryptionEngine.Dock = System.Windows.Forms.DockStyle.Fill;
comboBoxEncryptionEngine.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
comboBoxEncryptionEngine.FormattingEnabled = true;
- comboBoxEncryptionEngine.Location = new System.Drawing.Point(280, 4);
- comboBoxEncryptionEngine.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
+ comboBoxEncryptionEngine.Location = new System.Drawing.Point(197, 8);
+ comboBoxEncryptionEngine.Margin = new System.Windows.Forms.Padding(4);
comboBoxEncryptionEngine.Name = "comboBoxEncryptionEngine";
- comboBoxEncryptionEngine.Size = new System.Drawing.Size(196, 31);
+ comboBoxEncryptionEngine.Size = new System.Drawing.Size(196, 21);
comboBoxEncryptionEngine.Sorted = true;
comboBoxEncryptionEngine.TabIndex = 1;
//
@@ -75,10 +87,10 @@ namespace mRemoteNG.UI.Forms.OptionsPages
//
labelEncryptionEngine.AutoSize = true;
labelEncryptionEngine.Dock = System.Windows.Forms.DockStyle.Fill;
- labelEncryptionEngine.Location = new System.Drawing.Point(4, 0);
+ labelEncryptionEngine.Location = new System.Drawing.Point(8, 4);
labelEncryptionEngine.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
labelEncryptionEngine.Name = "labelEncryptionEngine";
- labelEncryptionEngine.Size = new System.Drawing.Size(268, 39);
+ labelEncryptionEngine.Size = new System.Drawing.Size(181, 29);
labelEncryptionEngine.TabIndex = 0;
labelEncryptionEngine.Text = "Encryption Engine";
labelEncryptionEngine.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
@@ -87,10 +99,10 @@ namespace mRemoteNG.UI.Forms.OptionsPages
//
labelBlockCipher.AutoSize = true;
labelBlockCipher.Dock = System.Windows.Forms.DockStyle.Fill;
- labelBlockCipher.Location = new System.Drawing.Point(4, 39);
+ labelBlockCipher.Location = new System.Drawing.Point(8, 33);
labelBlockCipher.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
labelBlockCipher.Name = "labelBlockCipher";
- labelBlockCipher.Size = new System.Drawing.Size(268, 39);
+ labelBlockCipher.Size = new System.Drawing.Size(181, 29);
labelBlockCipher.TabIndex = 2;
labelBlockCipher.Text = "Block Cipher Mode";
labelBlockCipher.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
@@ -101,20 +113,22 @@ namespace mRemoteNG.UI.Forms.OptionsPages
comboBoxBlockCipher.Dock = System.Windows.Forms.DockStyle.Fill;
comboBoxBlockCipher.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
comboBoxBlockCipher.FormattingEnabled = true;
- comboBoxBlockCipher.Location = new System.Drawing.Point(280, 43);
- comboBoxBlockCipher.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
+ comboBoxBlockCipher.Location = new System.Drawing.Point(197, 37);
+ comboBoxBlockCipher.Margin = new System.Windows.Forms.Padding(4);
comboBoxBlockCipher.Name = "comboBoxBlockCipher";
- comboBoxBlockCipher.Size = new System.Drawing.Size(196, 31);
+ comboBoxBlockCipher.Size = new System.Drawing.Size(196, 21);
comboBoxBlockCipher.TabIndex = 2;
//
// groupAdvancedSecurityOptions
//
+ groupAdvancedSecurityOptions.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
groupAdvancedSecurityOptions.Controls.Add(tableLayoutPanel1);
- groupAdvancedSecurityOptions.Location = new System.Drawing.Point(12, 51);
+ groupAdvancedSecurityOptions.Dock = System.Windows.Forms.DockStyle.Top;
+ groupAdvancedSecurityOptions.Location = new System.Drawing.Point(0, 25);
groupAdvancedSecurityOptions.Margin = new System.Windows.Forms.Padding(6);
groupAdvancedSecurityOptions.Name = "groupAdvancedSecurityOptions";
- groupAdvancedSecurityOptions.Padding = new System.Windows.Forms.Padding(4, 4, 4, 4);
- groupAdvancedSecurityOptions.Size = new System.Drawing.Size(906, 201);
+ groupAdvancedSecurityOptions.Padding = new System.Windows.Forms.Padding(4);
+ groupAdvancedSecurityOptions.Size = new System.Drawing.Size(610, 159);
groupAdvancedSecurityOptions.TabIndex = 1;
groupAdvancedSecurityOptions.TabStop = false;
groupAdvancedSecurityOptions.Text = "Advanced Security Options";
@@ -133,25 +147,26 @@ namespace mRemoteNG.UI.Forms.OptionsPages
tableLayoutPanel1.Controls.Add(comboBoxBlockCipher, 1, 1);
tableLayoutPanel1.Controls.Add(btnTestSettings, 1, 3);
tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Left;
- tableLayoutPanel1.Location = new System.Drawing.Point(4, 26);
- tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
+ tableLayoutPanel1.Location = new System.Drawing.Point(4, 19);
+ tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(4);
tableLayoutPanel1.Name = "tableLayoutPanel1";
+ tableLayoutPanel1.Padding = new System.Windows.Forms.Padding(4);
tableLayoutPanel1.RowCount = 4;
tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
- tableLayoutPanel1.Size = new System.Drawing.Size(480, 171);
+ tableLayoutPanel1.Size = new System.Drawing.Size(401, 136);
tableLayoutPanel1.TabIndex = 2;
//
// labelKdfIterations
//
labelKdfIterations.AutoSize = true;
labelKdfIterations.Dock = System.Windows.Forms.DockStyle.Fill;
- labelKdfIterations.Location = new System.Drawing.Point(4, 78);
+ labelKdfIterations.Location = new System.Drawing.Point(8, 62);
labelKdfIterations.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
labelKdfIterations.Name = "labelKdfIterations";
- labelKdfIterations.Size = new System.Drawing.Size(268, 37);
+ labelKdfIterations.Size = new System.Drawing.Size(181, 30);
labelKdfIterations.TabIndex = 4;
labelKdfIterations.Text = "Key Derivation Function Iterations";
labelKdfIterations.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
@@ -160,12 +175,12 @@ namespace mRemoteNG.UI.Forms.OptionsPages
//
numberBoxKdfIterations.Dock = System.Windows.Forms.DockStyle.Fill;
numberBoxKdfIterations.Increment = new decimal(new int[] { 1000, 0, 0, 0 });
- numberBoxKdfIterations.Location = new System.Drawing.Point(280, 82);
- numberBoxKdfIterations.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
+ numberBoxKdfIterations.Location = new System.Drawing.Point(197, 66);
+ numberBoxKdfIterations.Margin = new System.Windows.Forms.Padding(4);
numberBoxKdfIterations.Maximum = new decimal(new int[] { 50000, 0, 0, 0 });
numberBoxKdfIterations.Minimum = new decimal(new int[] { 1000, 0, 0, 0 });
numberBoxKdfIterations.Name = "numberBoxKdfIterations";
- numberBoxKdfIterations.Size = new System.Drawing.Size(196, 29);
+ numberBoxKdfIterations.Size = new System.Drawing.Size(196, 22);
numberBoxKdfIterations.TabIndex = 3;
numberBoxKdfIterations.ThousandsSeparator = true;
numberBoxKdfIterations.Value = new decimal(new int[] { 1000, 0, 0, 0 });
@@ -174,32 +189,121 @@ namespace mRemoteNG.UI.Forms.OptionsPages
//
btnTestSettings._mice = MrngButton.MouseState.OUT;
btnTestSettings.AutoSize = true;
- btnTestSettings.Dock = System.Windows.Forms.DockStyle.Right;
- btnTestSettings.Location = new System.Drawing.Point(294, 119);
- btnTestSettings.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
+ btnTestSettings.Location = new System.Drawing.Point(197, 96);
+ btnTestSettings.Margin = new System.Windows.Forms.Padding(4);
btnTestSettings.Name = "btnTestSettings";
- btnTestSettings.Size = new System.Drawing.Size(182, 52);
+ btnTestSettings.Padding = new System.Windows.Forms.Padding(4);
+ btnTestSettings.Size = new System.Drawing.Size(196, 33);
btnTestSettings.TabIndex = 4;
btnTestSettings.Text = "Test Settings";
btnTestSettings.UseVisualStyleBackColor = true;
btnTestSettings.Click += BtnTestSettings_Click;
//
+ // lblRegistrySettingsUsedInfo
+ //
+ lblRegistrySettingsUsedInfo.BackColor = System.Drawing.SystemColors.ControlLight;
+ lblRegistrySettingsUsedInfo.Dock = System.Windows.Forms.DockStyle.Top;
+ lblRegistrySettingsUsedInfo.ForeColor = System.Drawing.SystemColors.ControlText;
+ lblRegistrySettingsUsedInfo.Location = new System.Drawing.Point(0, 0);
+ lblRegistrySettingsUsedInfo.Name = "lblRegistrySettingsUsedInfo";
+ lblRegistrySettingsUsedInfo.Padding = new System.Windows.Forms.Padding(0, 2, 0, 0);
+ lblRegistrySettingsUsedInfo.Size = new System.Drawing.Size(610, 30);
+ lblRegistrySettingsUsedInfo.TabIndex = 3;
+ lblRegistrySettingsUsedInfo.Text = "Some settings are configured by your Administrator. Please contact your administrator for more information.";
+ lblRegistrySettingsUsedInfo.Visible = false;
+ //
+ // pnlOptions
+ //
+ pnlOptions.Controls.Add(groupAdvancedSecurityOptions);
+ pnlOptions.Controls.Add(chkEncryptCompleteFile);
+ pnlOptions.Dock = System.Windows.Forms.DockStyle.Top;
+ pnlOptions.Location = new System.Drawing.Point(0, 30);
+ pnlOptions.Name = "pnlOptions";
+ pnlOptions.Size = new System.Drawing.Size(610, 201);
+ pnlOptions.TabIndex = 2;
+ //
+ // groupPasswordGenerator
+ //
+ groupPasswordGenerator.Controls.Add(pnlPasswordTxtAndBtn);
+ groupPasswordGenerator.Controls.Add(lblPasswdGenDescription);
+ groupPasswordGenerator.Dock = System.Windows.Forms.DockStyle.Top;
+ groupPasswordGenerator.Location = new System.Drawing.Point(0, 231);
+ groupPasswordGenerator.Name = "groupPasswordGenerator";
+ groupPasswordGenerator.Size = new System.Drawing.Size(610, 116);
+ groupPasswordGenerator.TabIndex = 4;
+ groupPasswordGenerator.TabStop = false;
+ groupPasswordGenerator.Text = "Secure Key Generator";
+ //
+ // pnlPasswordTxtAndBtn
+ //
+ pnlPasswordTxtAndBtn.ColumnCount = 2;
+ pnlPasswordTxtAndBtn.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 63.91437F));
+ pnlPasswordTxtAndBtn.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 36.08563F));
+ pnlPasswordTxtAndBtn.Controls.Add(txtPasswdGenerator, 0, 0);
+ pnlPasswordTxtAndBtn.Controls.Add(btnPasswdGenerator, 1, 0);
+ pnlPasswordTxtAndBtn.Location = new System.Drawing.Point(4, 43);
+ pnlPasswordTxtAndBtn.Name = "pnlPasswordTxtAndBtn";
+ pnlPasswordTxtAndBtn.RowCount = 1;
+ pnlPasswordTxtAndBtn.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
+ pnlPasswordTxtAndBtn.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
+ pnlPasswordTxtAndBtn.Size = new System.Drawing.Size(327, 31);
+ pnlPasswordTxtAndBtn.TabIndex = 1;
+ //
+ // txtPasswdGenerator
+ //
+ txtPasswdGenerator.Anchor = System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
+ txtPasswdGenerator.Location = new System.Drawing.Point(3, 4);
+ txtPasswdGenerator.Name = "txtPasswdGenerator";
+ txtPasswdGenerator.PasswordChar = '*';
+ txtPasswdGenerator.Size = new System.Drawing.Size(203, 22);
+ txtPasswdGenerator.TabIndex = 1;
+ txtPasswdGenerator.TextChanged += txtPasswdGenerator_TextChanged;
+ //
+ // btnPasswdGenerator
+ //
+ btnPasswdGenerator.Anchor = System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
+ btnPasswdGenerator.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
+ btnPasswdGenerator.Enabled = false;
+ btnPasswdGenerator.Location = new System.Drawing.Point(212, 4);
+ btnPasswdGenerator.Name = "btnPasswdGenerator";
+ btnPasswdGenerator.Size = new System.Drawing.Size(112, 23);
+ btnPasswdGenerator.TabIndex = 2;
+ btnPasswdGenerator.Text = "Copy to Clipboard";
+ btnPasswdGenerator.UseVisualStyleBackColor = true;
+ btnPasswdGenerator.Click += btnPasswdGenerator_Click;
+ //
+ // lblPasswdGenDescription
+ //
+ lblPasswdGenDescription.AutoSize = true;
+ lblPasswdGenDescription.Dock = System.Windows.Forms.DockStyle.Top;
+ lblPasswdGenDescription.Location = new System.Drawing.Point(3, 18);
+ lblPasswdGenDescription.Name = "lblPasswdGenDescription";
+ lblPasswdGenDescription.Size = new System.Drawing.Size(327, 13);
+ lblPasswdGenDescription.TabIndex = 0;
+ lblPasswdGenDescription.Text = "Generate an encrypted password suitable for registry settings.";
+ //
// SecurityPage
//
- AutoScaleDimensions = new System.Drawing.SizeF(144F, 144F);
+ AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
- Controls.Add(chkEncryptCompleteFile);
- Controls.Add(groupAdvancedSecurityOptions);
- Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
+ Controls.Add(groupPasswordGenerator);
+ Controls.Add(pnlOptions);
+ Controls.Add(lblRegistrySettingsUsedInfo);
+ Margin = new System.Windows.Forms.Padding(4);
Name = "SecurityPage";
- Size = new System.Drawing.Size(915, 735);
+ Size = new System.Drawing.Size(610, 490);
groupAdvancedSecurityOptions.ResumeLayout(false);
groupAdvancedSecurityOptions.PerformLayout();
tableLayoutPanel1.ResumeLayout(false);
tableLayoutPanel1.PerformLayout();
((System.ComponentModel.ISupportInitialize)numberBoxKdfIterations).EndInit();
+ pnlOptions.ResumeLayout(false);
+ pnlOptions.PerformLayout();
+ groupPasswordGenerator.ResumeLayout(false);
+ groupPasswordGenerator.PerformLayout();
+ pnlPasswordTxtAndBtn.ResumeLayout(false);
+ pnlPasswordTxtAndBtn.PerformLayout();
ResumeLayout(false);
- PerformLayout();
}
#endregion
@@ -210,9 +314,16 @@ namespace mRemoteNG.UI.Forms.OptionsPages
private Controls.MrngLabel labelBlockCipher;
private MrngComboBox comboBoxBlockCipher;
private MrngGroupBox groupAdvancedSecurityOptions;
- private Controls.MrngNumericUpDown numberBoxKdfIterations;
+ internal Controls.MrngNumericUpDown numberBoxKdfIterations;
private Controls.MrngLabel labelKdfIterations;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
private MrngButton btnTestSettings;
+ internal System.Windows.Forms.Label lblRegistrySettingsUsedInfo;
+ private System.Windows.Forms.Panel pnlOptions;
+ private System.Windows.Forms.GroupBox groupPasswordGenerator;
+ private System.Windows.Forms.TableLayoutPanel pnlPasswordTxtAndBtn;
+ private System.Windows.Forms.TextBox txtPasswdGenerator;
+ private System.Windows.Forms.Button btnPasswdGenerator;
+ private System.Windows.Forms.Label lblPasswdGenDescription;
}
}
diff --git a/mRemoteNG/UI/Forms/OptionsPages/SecurityPage.cs b/mRemoteNG/UI/Forms/OptionsPages/SecurityPage.cs
index 502c6816..e07b03c5 100644
--- a/mRemoteNG/UI/Forms/OptionsPages/SecurityPage.cs
+++ b/mRemoteNG/UI/Forms/OptionsPages/SecurityPage.cs
@@ -10,12 +10,22 @@ using mRemoteNG.Security;
using mRemoteNG.Security.Factories;
using mRemoteNG.Resources.Language;
using System.Runtime.Versioning;
+using mRemoteNG.Config.Settings.Registry;
+using mRemoteNG.Security.SymmetricEncryption;
namespace mRemoteNG.UI.Forms.OptionsPages
{
[SupportedOSPlatform("windows")]
public sealed partial class SecurityPage : OptionsPage
{
+ #region Private Fields
+ private OptRegistrySecurityPage pageRegSettingsInstance;
+
+ private readonly Timer clipboardClearTimer = new() { Interval = 1000 };
+ private const int clipboardClearSeconds = 30;
+ private int countdownSeconds = clipboardClearSeconds;
+ #endregion
+
public SecurityPage()
{
InitializeComponent();
@@ -41,6 +51,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages
labelKdfIterations.Text = Language.EncryptionKeyDerivationIterations;
groupAdvancedSecurityOptions.Text = Language.AdvancedSecurityOptions;
btnTestSettings.Text = Language.TestSettings;
+ lblRegistrySettingsUsedInfo.Text = Language.OptionsCompanyPolicyMessage;
}
public override void LoadSettings()
@@ -60,6 +71,41 @@ namespace mRemoteNG.UI.Forms.OptionsPages
Properties.OptionsSecurityPage.Default.EncryptionKeyDerivationIterations = (int)numberBoxKdfIterations.Value;
}
+ public override void LoadRegistrySettings()
+ {
+ Type settingsType = typeof(OptRegistrySecurityPage);
+ RegistryLoader.RegistrySettings.TryGetValue(settingsType, out var settings);
+ pageRegSettingsInstance = settings as OptRegistrySecurityPage;
+
+ RegistryLoader.Cleanup(settingsType);
+
+ // ***
+ // Disable controls based on the registry settings.
+ //
+ if (pageRegSettingsInstance.EncryptCompleteConnectionsFile.IsSet)
+ DisableControl(chkEncryptCompleteFile);
+
+ if (pageRegSettingsInstance.EncryptionEngine.IsSet)
+ DisableControl(comboBoxEncryptionEngine);
+
+ if (pageRegSettingsInstance.EncryptionBlockCipherMode.IsSet)
+ DisableControl(comboBoxBlockCipher);
+
+ if (pageRegSettingsInstance.EncryptionKeyDerivationIterations.IsSet)
+ DisableControl(numberBoxKdfIterations);
+
+ // Updates the visibility of the information label indicating whether registry settings are used.
+ lblRegistrySettingsUsedInfo.Visible = ShowRegistrySettingsUsedInfo();
+ }
+
+ private bool ShowRegistrySettingsUsedInfo()
+ {
+ return pageRegSettingsInstance.EncryptCompleteConnectionsFile.IsSet
+ || pageRegSettingsInstance.EncryptionEngine.IsSet
+ || pageRegSettingsInstance.EncryptionBlockCipherMode.IsSet
+ || pageRegSettingsInstance.EncryptionKeyDerivationIterations.IsSet;
+ }
+
public override void RevertSettings()
{
}
@@ -101,5 +147,108 @@ namespace mRemoteNG.UI.Forms.OptionsPages
MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
+
+
+ ///
+ /// Encrypts the entered password, copies it to the clipboard, and starts a 30-second timer to clear the clipboard.
+ /// Also updates a countdown display in the UI.
+ ///
+ /// Event source.
+ /// Event data.
+ private void btnPasswdGenerator_Click(object sender, EventArgs e)
+ {
+ if (string.IsNullOrEmpty(txtPasswdGenerator.Text)) return;
+
+ var cryptographyProvider = new LegacyRijndaelCryptographyProvider();
+
+ try
+ {
+ // Encrypt and set the clipboard content
+ string encryptedText = cryptographyProvider.Encrypt(txtPasswdGenerator.Text, Runtime.EncryptionKey);
+ System.Windows.Clipboard.SetText(encryptedText);
+ }
+ catch (System.Runtime.InteropServices.COMException)
+ {
+ Runtime.MessageCollector.AddMessage(Messages.MessageClass.ErrorMsg, "Failed to set clipboard content. Please try again.");
+ return;
+ }
+
+ // Reset the countdown and start the timer
+ ResetAndStartTimer();
+ }
+
+ ///
+ /// Resets the countdown timer and starts it.
+ ///
+ private void ResetAndStartTimer()
+ {
+ // Stop the timer if it's running
+ if (clipboardClearTimer.Enabled)
+ {
+ clipboardClearTimer.Stop();
+ }
+
+ countdownSeconds = clipboardClearSeconds; // Reset countdown
+ clipboardClearTimer.Tick -= ClipboardClearTimer_Tick; // Detach in case it was previously attached
+ clipboardClearTimer.Tick += ClipboardClearTimer_Tick; // Re-attach event handler
+ clipboardClearTimer.Start();
+ }
+
+ ///
+ /// Handles the timer tick event for clearing the clipboard.
+ /// Decrements the countdown, updates the UI label, and clears the clipboard when the countdown reaches zero.
+ /// Stops the timer and handles any errors that occur during clipboard clearing.
+ ///
+ /// Event source.
+ /// Event data.
+ private void ClipboardClearTimer_Tick(object sender, EventArgs e)
+ {
+ if (countdownSeconds > 0)
+ {
+ countdownSeconds--;
+ }
+ else
+ {
+ StopClipboardClearTimer();
+ ClearClipboard();
+ }
+ }
+
+ ///
+ /// Stops the clipboard clear timer and detaches the event handler.
+ ///
+ private void StopClipboardClearTimer()
+ {
+ clipboardClearTimer.Stop();
+ clipboardClearTimer.Tick -= ClipboardClearTimer_Tick;
+ }
+
+ ///
+ /// Clears the clipboard and handles any exceptions that occur.
+ ///
+ private void ClearClipboard()
+ {
+ try
+ {
+ System.Windows.Clipboard.Clear();
+ txtPasswdGenerator.Clear();
+ }
+ catch (System.Runtime.InteropServices.COMException)
+ {
+ Runtime.MessageCollector.AddMessage(Messages.MessageClass.ErrorMsg, "Failed to clear clipboard.");
+ }
+ }
+
+ ///
+ /// Handles the TextChanged event for the password generator TextBox.
+ /// Enables or disables the button depending on whether the TextBox has content.
+ ///
+ /// Event source.
+ /// Event data.
+ private void txtPasswdGenerator_TextChanged(object sender, EventArgs e)
+ {
+ // Enable the button if there's text in the TextBox, disable it otherwise.
+ btnPasswdGenerator.Enabled = !string.IsNullOrWhiteSpace(txtPasswdGenerator.Text);
+ }
}
}
\ No newline at end of file
diff --git a/mRemoteNG/UI/Forms/OptionsPages/SecurityPage.resx b/mRemoteNG/UI/Forms/OptionsPages/SecurityPage.resx
index f298a7be..8b2ff64a 100644
--- a/mRemoteNG/UI/Forms/OptionsPages/SecurityPage.resx
+++ b/mRemoteNG/UI/Forms/OptionsPages/SecurityPage.resx
@@ -1,4 +1,64 @@
-
+
+
+
diff --git a/mRemoteNGDocumentation/registry/credential_settings.rst b/mRemoteNGDocumentation/registry/credential_settings.rst
index 17a26d05..81fda2e9 100644
--- a/mRemoteNGDocumentation/registry/credential_settings.rst
+++ b/mRemoteNGDocumentation/registry/credential_settings.rst
@@ -18,7 +18,7 @@ Common
Allow Export Usernames
----------------------
-Determines whether exporting usernames is allowed.
+Specifies whether the export of usernames for saved connections is allowed.
- **Value Name:** ``AllowExportUsernames``
- **Value Type:** ``REG_SZ``
@@ -30,7 +30,7 @@ Determines whether exporting usernames is allowed.
Allow Export Passwords
----------------------
-Determines whether exporting passwords is allowed.
+Specifies whether the export of passwords for saved connections is allowed.
- **Value Name:** ``AllowExportPasswords``
- **Value Type:** ``REG_SZ``
@@ -42,7 +42,7 @@ Determines whether exporting passwords is allowed.
Allow Save Usernames
--------------------
-Determines whether saving usernames is allowed.
+Specifies whether the saving of usernames for saved connections is allowed.
- **Value Name:** ``AllowSaveUsernames``
- **Value Type:** ``REG_SZ``
@@ -61,7 +61,7 @@ Determines whether saving usernames is allowed.
Allow Save Passwords
--------------------
-Determines whether saving passwords is allowed.
+Specifies whether the saving of passwords for saved connections is allowed.
- **Value Name:** ``AllowSavePasswords``
- **Value Type:** ``REG_SZ``
@@ -154,7 +154,8 @@ Specifies the default domain.
Default Username Enabled
------------------------
-Specifies that entering the custom default username field is enabled.
+Controls whether the default username field is enabled or disabled.
+Locking the field may make more sense than disabling the entire settings option.
- **Value Name:** ``DefaultUsernameEnabled``
- **Value Type:** ``REG_SZ``
@@ -166,7 +167,8 @@ Specifies that entering the custom default username field is enabled.
Default Password Enabled
------------------------
-Specifies that entering the custom default password field is enabled.
+Controls whether the default password field is enabled or disabled.
+Locking the field may make more sense than disabling the entire settings option.
- **Value Name:** ``DefaultPasswordEnabled``
- **Value Type:** ``REG_SZ``
@@ -178,7 +180,8 @@ Specifies that entering the custom default password field is enabled.
Default User Via API Enabled
----------------------------
-Specifies that entering the custom default api user field is enabled.
+Controls whether the default user via API field is enabled or disabled.
+Locking the field may make more sense than disabling the entire settings option.
- **Value Name:** ``DefaultUserViaAPIEnabled``
- **Value Type:** ``REG_SZ``
diff --git a/mRemoteNGDocumentation/registry/security_settings.rst b/mRemoteNGDocumentation/registry/security_settings.rst
new file mode 100644
index 00000000..dc0ef564
--- /dev/null
+++ b/mRemoteNGDocumentation/registry/security_settings.rst
@@ -0,0 +1,82 @@
+*****************
+Security Settings
+*****************
+.. versionadded:: v1.77.3
+
+.. warning::
+ Before proceeding with any changes to the Windows Registry, it is imperative that you carefully read and comprehend the
+ **Modifying the Registry**, **Restricted Registry Settings** and **Disclaimer**
+ on :doc:`Registry Settings Infromation `.
+
+
+Options
+====================
+Configure the options page to modify functionalities as described.
+
+- **Registry Hive:** ``HKEY_LOCAL_MACHINE``
+- **Registry Path:** ``SOFTWARE\mRemoteNG\Security\Options``
+
+Encrypt Complete Connections File
+---------------------------------
+Specifies the encryption engine used for encryption.
+
+- **Value Name:** ``EncryptCompleteConnectionsFile``
+- **Value Type:** ``REG_SZ``
+- **Values:**
+
+ - Enable: ``true``
+ - Disable: ``false``
+
+
+Encryption Engine
+-----------------
+Specifies the encryption engine used for encryption.
+
+- **Value Name:** ``EncryptionEngine``
+- **Value Type:** ``REG_SZ``
+- **Values:**
+
+ - ``AES``
+ - ``Serpent``
+ - ``Twofish``
+
+
+Encryption Block Cipher Mode
+----------------------------
+Specifies the block cipher mode used for encryption.
+
+- **Value Name:** ``EncryptionBlockCipherMode``
+- **Value Type:** ``REG_SZ``
+- **Values:**
+
+ - ``GCM``
+ - ``CCM``
+ - ``EAX``
+
+
+Encryption Key Derivation Iterations
+------------------------------------
+Specifies the number of iterations used in the encryption key derivation process.
+
+- **Value Name:** ``EncryptionKeyDerivationIterations``
+- **Value Type:** ``REG_DWORD``
+- **Values:**
+
+ - Minimum: ``1000``
+ - Maximum: ``50000``
+
+
+Registry Template
+=================
+
+.. code::
+
+ Windows Registry Editor Version 5.00
+
+ [HKEY_LOCAL_MACHINE\SOFTWARE\mRemoteNG\Security]
+
+ [HKEY_LOCAL_MACHINE\SOFTWARE\mRemoteNG\Security\Options]
+ "EncryptionEngine"="AES"
+ "EncryptionBlockCipherMode"="GCM"
+ "EncryptCompleteConnectionsFile"="false"
+ "EncryptionKeyDerivationIterations"=dword:00009c40
diff --git a/mRemoteNGDocumentation/registry_settings_guide.rst b/mRemoteNGDocumentation/registry_settings_guide.rst
index dd92db66..9b149600 100644
--- a/mRemoteNGDocumentation/registry_settings_guide.rst
+++ b/mRemoteNGDocumentation/registry_settings_guide.rst
@@ -29,4 +29,5 @@ Make changes with caution and ensure that you have backups before making any adj
registry/notification_settings.rst
registry/credential_settings.rst
registry/sqlServer_settings.rst
- registry/updates_settings.rst
\ No newline at end of file
+ registry/updates_settings.rst
+ registry/security_settings.rst
\ No newline at end of file