Skip to content

Commit

Permalink
Added Private Key Auth option
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexey Murashkevich committed Oct 1, 2023
1 parent 7a7299e commit aec3fdc
Show file tree
Hide file tree
Showing 8 changed files with 401 additions and 133 deletions.
217 changes: 166 additions & 51 deletions SSH.CommandSender/Dialogs/HostEditorDialog.Designer.cs

Large diffs are not rendered by default.

184 changes: 120 additions & 64 deletions SSH.CommandSender/Dialogs/HostEditorDialog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Newtonsoft.Json;
using SSH.CommandSender.Domain;
using SSH.CommandSender.Properties;

Expand All @@ -34,9 +35,7 @@ private void BindControls()
this.txtName.Text = this.HostDetails.Name;
this.txtHost.Text = this.HostDetails.Host;
this.numericPort.Value = this.HostDetails.Port;
this.txtUsername.Text = this.HostDetails.Username;
this.txtPassword.Text = this.HostDetails.Password;

BindAuth();
this.txtName.DataBindings.Add("Text", this.HostDetails, "Name", false,
DataSourceUpdateMode.OnValidation);

Expand All @@ -45,10 +44,82 @@ private void BindControls()

this.numericPort.DataBindings.Add("Value", this.HostDetails, "Port", false,
DataSourceUpdateMode.OnValidation);
this.txtUsername.DataBindings.Add("Text", this.HostDetails, "Username", false,
DataSourceUpdateMode.OnValidation);
this.txtPassword.DataBindings.Add("Text", this.HostDetails, "Password", false,
this.txtUsername.DataBindings.Add("Text", this.HostDetails.AuthenticationDetails, "Username", false,
DataSourceUpdateMode.OnValidation);



}

private void BindAuth()
{
this.txtUsername.Text = this.HostDetails.AuthenticationDetails.Username;
switch (this.HostDetails.AuthenticationDetails)
{
case SshHostDetails.PasswordAuth passwordAuth:

comboAuthMethod.SelectedIndex = 0;
this.txtPassword.Text = passwordAuth.Password;

if (txtPassword.DataBindings.Count == 0)
{
this.txtPassword.DataBindings.Add("Text", this.HostDetails.AuthenticationDetails as SshHostDetails.PasswordAuth, "Password", false,
DataSourceUpdateMode.OnValidation);
}

HideRowInPanel(tableLayoutPanelMain, new List<int>() {7, 8});

break;
case SshHostDetails.PrivateKeyFileAuth privateKeyFileAuth:
comboAuthMethod.SelectedIndex = 1;
txtPassPhrase.Text = privateKeyFileAuth.PassPhrase;
txtPathToKeyFile.Text = privateKeyFileAuth.PathToKeyFile;

if (txtPassPhrase.DataBindings.Count == 0)
{
this.txtPassPhrase.DataBindings.Add("Text", this.HostDetails.AuthenticationDetails as SshHostDetails.PrivateKeyFileAuth, "PassPhrase", false,
DataSourceUpdateMode.OnValidation);
}

if (txtPathToKeyFile.DataBindings.Count == 0)
{
this.txtPathToKeyFile.DataBindings.Add("Text", this.HostDetails.AuthenticationDetails as SshHostDetails.PrivateKeyFileAuth, "PathToKeyFile", false,
DataSourceUpdateMode.OnValidation);
}
HideRowInPanel(tableLayoutPanelMain, new List<int>() { 6 });

break;
}

//HideRowInPanel(tableLayoutPanelMain, 6);
}

private void HideRowInPanel(TableLayoutPanel tableLayoutPanel, List<int> rowIndexes)
{
for (int i = 0; i < tableLayoutPanel.RowCount; i++)
{
if (rowIndexes.Any(x => x == i))
{
tableLayoutPanel.RowStyles[i].SizeType = SizeType.Absolute;
tableLayoutPanel.RowStyles[i].Height = 0;
foreach (Control control in tableLayoutPanel.Controls)
{
if (rowIndexes.Any(x => x == tableLayoutPanel.GetRow(control)))
{
control.Hide();
}
else
{
control.Show();
}
}
}
else
{
tableLayoutPanel.RowStyles[i].SizeType = SizeType.Percent;
tableLayoutPanel.RowStyles[i].Height = 50;
}
}
}

private void lnkTogglePasswordField_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
Expand All @@ -69,74 +140,59 @@ private void lnkTogglePasswordField_LinkClicked(object sender, LinkLabelLinkClic
}
}

private void txtName_TextChanged(object sender, EventArgs e)
private void lnkTogglePassPhrase_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(HostEditorDialog));

}

private void lblName_Click(object sender, EventArgs e)
{

}

private void tableLayoutPanelButtons_Paint(object sender, PaintEventArgs e)
{

}

private void btnCancel_Click(object sender, EventArgs e)
{

}

private void btnSave_Click(object sender, EventArgs e)
{

}

private void lblHost_Click(object sender, EventArgs e)
{

}

private void txtHost_TextChanged(object sender, EventArgs e)
{

}

private void lblPort_Click(object sender, EventArgs e)
{

}

private void lblUsername_Click(object sender, EventArgs e)
{

}

private void txtUsername_TextChanged(object sender, EventArgs e)
{

}

private void lblPassword_Click(object sender, EventArgs e)
{

}

private void txtPassword_TextChanged(object sender, EventArgs e)
{
if (txtPassPhrase.PasswordChar == '●')
{
txtPassPhrase.PasswordChar = '\0';
this.lnkTogglePasswordField.Image = ((System.Drawing.Image)(resources.GetObject("icon-closed-eye")));

}
else
{
txtPassPhrase.PasswordChar = '●';
this.lnkTogglePasswordField.Image = ((System.Drawing.Image)(resources.GetObject("icon-opened-eye")));
}
}

private void tableLayoutPanelMain_Paint(object sender, PaintEventArgs e)
private void btnBrowseKeyPath_Click(object sender, EventArgs e)
{

using (OpenFileDialog openFileDialog = new OpenFileDialog())
{
openFileDialog.Filter = "All files (*.*)|*.*";
openFileDialog.FilterIndex = 1;
openFileDialog.RestoreDirectory = true;
openFileDialog.Multiselect = false;

if (openFileDialog.ShowDialog() == DialogResult.OK)
{
if (openFileDialog.FileName != null && openFileDialog.FileName.Length > 0)
{
txtPathToKeyFile.Text = openFileDialog.FileName;
(this.HostDetails.AuthenticationDetails as SshHostDetails.PrivateKeyFileAuth).PathToKeyFile = openFileDialog.FileName;
}

}
}
}

private void numericPort_ValueChanged(object sender, EventArgs e)
private void comboAuthMethod_SelectedIndexChanged(object sender, EventArgs e)
{
if (comboAuthMethod.SelectedIndex == 0)
{
//pass auth
this.HostDetails.AuthenticationDetails = new SshHostDetails.PasswordAuth(this.HostDetails.AuthenticationDetails.Username, string.Empty);
}
else
{
//key file auth
this.HostDetails.AuthenticationDetails =
new SshHostDetails.PrivateKeyFileAuth(this.HostDetails.AuthenticationDetails.Username, string.Empty, string.Empty);
}

BindAuth();
}
}
}
7 changes: 0 additions & 7 deletions SSH.CommandSender/Dialogs/HostEditorDialog.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1799,11 +1799,4 @@
AACgVQAAoFUAAKBFAACoVQAAoFUAAL/9AAC//QAAgAEAAIABAACAAQAA//8AAP//AAA=
</value>
</data>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="icon-closed-eye" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Assets\icon-closed-eye.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="icon-opened-eye" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Assets\icon-opened-eye.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>
31 changes: 31 additions & 0 deletions SSH.CommandSender/Domain/AuthJsonConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace SSH.CommandSender.Domain
{
public class AuthJsonConverter : JsonConverter<SshHostDetails.Auth>
{
public override void WriteJson(JsonWriter writer, SshHostDetails.Auth value, JsonSerializer serializer)
{
serializer.Serialize(writer, value);
}

public override SshHostDetails.Auth ReadJson(JsonReader reader, Type objectType, SshHostDetails.Auth existingValue, bool hasExistingValue, JsonSerializer serializer)
{
var jObject = JObject.Load(reader);
if (jObject["PathToKeyFile"] == null)
{
return new SshHostDetails.PasswordAuth(jObject["Username"].Value<string>(),
jObject["Password"].Value<string>());
}
else
{
return new SshHostDetails.PrivateKeyFileAuth(jObject["Username"].Value<string>(),
jObject["PathToKeyFile"].Value<string>(), jObject["PassPhrase"].Value<string>());

}

}
}
}
86 changes: 79 additions & 7 deletions SSH.CommandSender/Domain/SshHostDetails.cs
Original file line number Diff line number Diff line change
@@ -1,28 +1,100 @@
using System;
using Newtonsoft.Json;
using Renci.SshNet;

namespace SSH.CommandSender.Domain
{
public class SshHostDetails : ICloneable
{
public abstract class Auth
{
public string Username { get; set; }

public Auth(string username)
{
Username = username;
}

public abstract SshClient CreateSshClient(string host, ushort port);

public abstract bool Validate();
}

public class PrivateKeyFileAuth : Auth
{
public string PathToKeyFile { get; set; }
public string PassPhrase { get; set; }

public PrivateKeyFileAuth(string username, string pathToKeyFile, string passPhrase) : base(username)
{
PathToKeyFile = pathToKeyFile;
PassPhrase = passPhrase;
}

public override SshClient CreateSshClient(string host, ushort port)
{
return new SshClient(host, port, Username, new PrivateKeyFile(this.PathToKeyFile, this.PassPhrase));

}

public override bool Validate()
{
return string.IsNullOrWhiteSpace(this.Username) == false &&
string.IsNullOrWhiteSpace(this.PathToKeyFile) == false;
}
}

public class PasswordAuth : Auth
{
public string Password { get; set; }

public PasswordAuth(string username, string password) : base(username)
{
Password = password;
}

public override SshClient CreateSshClient(string host, ushort port)
{
return new SshClient(host, port, Username, Password);
}

public override bool Validate()
{
return string.IsNullOrWhiteSpace(this.Username) == false;
}
}
public string Name { get; set; }
public string Host { get; set; }
public ushort Port { get; }
public string Username { get; set; }
public string Password { get; set; }
public ushort Port { get; set; }

public SshHostDetails(string name = "", string host = "",string username = "", string password = "", ushort port = 22)
[JsonConverter(typeof(AuthJsonConverter))]
public Auth AuthenticationDetails { get; set; }

public SshHostDetails(string name = "", string host = "", ushort port = 22, Auth authenticationDetails = null)
{
Name = name;
Host = host;
Port = port;
Username = username;
Password = password;

if (authenticationDetails == null)
{
AuthenticationDetails = new PasswordAuth(string.Empty, string.Empty);
}
else
{
AuthenticationDetails = authenticationDetails;
}
}

public SshClient CreateSshClient()
{
return AuthenticationDetails.CreateSshClient(Host,Port);

}

public object Clone()
{
return new SshHostDetails(this.Name, this.Host, this.Username, this.Password, this.Port);
return new SshHostDetails(this.Name, this.Host, this.Port, AuthenticationDetails);
}
}
}
4 changes: 2 additions & 2 deletions SSH.CommandSender/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.6")]
[assembly: AssemblyFileVersion("1.0.0.6")]
[assembly: AssemblyVersion("1.0.0.7")]
[assembly: AssemblyFileVersion("1.0.0.7")]
1 change: 1 addition & 0 deletions SSH.CommandSender/SSH.CommandSender.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
<Compile Include="Dialogs\HostEditorDialog.Designer.cs">
<DependentUpon>HostEditorDialog.cs</DependentUpon>
</Compile>
<Compile Include="Domain\AuthJsonConverter.cs" />
<Compile Include="Domain\SshCommandDetails.cs" />
<Compile Include="Domain\SshCommandExtensions.cs" />
<Compile Include="Domain\SshHostDetails.cs" />
Expand Down

0 comments on commit aec3fdc

Please sign in to comment.