Skip to content

Commit

Permalink
Add IPrivateKeyFile
Browse files Browse the repository at this point in the history
So Extension can add own PrivateKeyFiles, e.g. PuttyKeyFile.
  • Loading branch information
darinkes committed Aug 16, 2021
1 parent 8a6cc88 commit f7fad26
Show file tree
Hide file tree
Showing 8 changed files with 56 additions and 33 deletions.
15 changes: 15 additions & 0 deletions src/Renci.SshNet/IPrivateKeyFile.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using Renci.SshNet.Security;

namespace Renci.SshNet
{
/// <summary>
/// Represents private key file interface.
/// </summary>
public interface IPrivateKeyFile
{
/// <summary>
/// Gets the host key.
/// </summary>
HostAlgorithm HostKey { get; }
}
}
6 changes: 3 additions & 3 deletions src/Renci.SshNet/NetConfClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ public NetConfClient(string host, string username, string password)
/// <exception cref="ArgumentException"><paramref name="host"/> is invalid, -or- <paramref name="username"/> is <c>null</c> or contains only whitespace characters.</exception>
/// <exception cref="ArgumentOutOfRangeException"><paramref name="port"/> is not within <see cref="IPEndPoint.MinPort"/> and <see cref="IPEndPoint.MaxPort"/>.</exception>
[SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Justification = "Disposed in Dispose(bool) method.")]
public NetConfClient(string host, int port, string username, params PrivateKeyFile[] keyFiles)
public NetConfClient(string host, int port, string username, params IPrivateKeyFile[] keyFiles)
: this(new PrivateKeyConnectionInfo(host, port, username, keyFiles), true)
{
}
Expand All @@ -116,7 +116,7 @@ public NetConfClient(string host, int port, string username, params PrivateKeyFi
/// <param name="keyFiles">Authentication private key file(s) .</param>
/// <exception cref="ArgumentNullException"><paramref name="keyFiles"/> is <c>null</c>.</exception>
/// <exception cref="ArgumentException"><paramref name="host"/> is invalid, -or- <paramref name="username"/> is <c>null</c> or contains only whitespace characters.</exception>
public NetConfClient(string host, string username, params PrivateKeyFile[] keyFiles)
public NetConfClient(string host, string username, params IPrivateKeyFile[] keyFiles)
: this(host, ConnectionInfo.DefaultPort, username, keyFiles)
{
}
Expand Down Expand Up @@ -163,7 +163,7 @@ internal NetConfClient(ConnectionInfo connectionInfo, bool ownsConnectionInfo, I
/// <value>
/// The NetConf server capabilities.
/// </value>
public XmlDocument ServerCapabilities
public XmlDocument ServerCapabilities
{
get { return _netConfSession.ServerCapabilities; }
}
Expand Down
6 changes: 3 additions & 3 deletions src/Renci.SshNet/PrivateKeyAuthenticationMethod.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,21 @@ public override string Name
/// <summary>
/// Gets the key files used for authentication.
/// </summary>
public ICollection<PrivateKeyFile> KeyFiles { get; private set; }
public ICollection<IPrivateKeyFile> KeyFiles { get; private set; }

/// <summary>
/// Initializes a new instance of the <see cref="PrivateKeyAuthenticationMethod"/> class.
/// </summary>
/// <param name="username">The username.</param>
/// <param name="keyFiles">The key files.</param>
/// <exception cref="ArgumentException"><paramref name="username"/> is whitespace or <c>null</c>.</exception>
public PrivateKeyAuthenticationMethod(string username, params PrivateKeyFile[] keyFiles)
public PrivateKeyAuthenticationMethod(string username, params IPrivateKeyFile[] keyFiles)
: base(username)
{
if (keyFiles == null)
throw new ArgumentNullException("keyFiles");

KeyFiles = new Collection<PrivateKeyFile>(keyFiles);
KeyFiles = new Collection<IPrivateKeyFile>(keyFiles);
}

/// <summary>
Expand Down
16 changes: 8 additions & 8 deletions src/Renci.SshNet/PrivateKeyConnectionInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class PrivateKeyConnectionInfo : ConnectionInfo, IDisposable
/// <summary>
/// Gets the key files used for authentication.
/// </summary>
public ICollection<PrivateKeyFile> KeyFiles { get; private set; }
public ICollection<IPrivateKeyFile> KeyFiles { get; private set; }

/// <summary>
/// Initializes a new instance of the <see cref="PrivateKeyConnectionInfo"/> class.
Expand All @@ -40,7 +40,7 @@ public PrivateKeyConnectionInfo(string host, string username, params PrivateKeyF
/// <param name="port">Connection port.</param>
/// <param name="username">Connection username.</param>
/// <param name="keyFiles">Connection key files.</param>
public PrivateKeyConnectionInfo(string host, int port, string username, params PrivateKeyFile[] keyFiles)
public PrivateKeyConnectionInfo(string host, int port, string username, params IPrivateKeyFile[] keyFiles)
: this(host, port, username, ProxyTypes.None, string.Empty, 0, string.Empty, string.Empty, keyFiles)
{
}
Expand All @@ -55,7 +55,7 @@ public PrivateKeyConnectionInfo(string host, int port, string username, params P
/// <param name="proxyHost">The proxy host.</param>
/// <param name="proxyPort">The proxy port.</param>
/// <param name="keyFiles">The key files.</param>
public PrivateKeyConnectionInfo(string host, int port, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, params PrivateKeyFile[] keyFiles)
public PrivateKeyConnectionInfo(string host, int port, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, params IPrivateKeyFile[] keyFiles)
: this(host, port, username, proxyType, proxyHost, proxyPort, string.Empty, string.Empty, keyFiles)
{
}
Expand All @@ -71,7 +71,7 @@ public PrivateKeyConnectionInfo(string host, int port, string username, ProxyTyp
/// <param name="proxyPort">The proxy port.</param>
/// <param name="proxyUsername">The proxy username.</param>
/// <param name="keyFiles">The key files.</param>
public PrivateKeyConnectionInfo(string host, int port, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, params PrivateKeyFile[] keyFiles)
public PrivateKeyConnectionInfo(string host, int port, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, params IPrivateKeyFile[] keyFiles)
: this(host, port, username, proxyType, proxyHost, proxyPort, proxyUsername, string.Empty, keyFiles)
{
}
Expand Down Expand Up @@ -100,7 +100,7 @@ public PrivateKeyConnectionInfo(string host, string username, ProxyTypes proxyTy
/// <param name="proxyPort">The proxy port.</param>
/// <param name="proxyUsername">The proxy username.</param>
/// <param name="keyFiles">The key files.</param>
public PrivateKeyConnectionInfo(string host, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, params PrivateKeyFile[] keyFiles)
public PrivateKeyConnectionInfo(string host, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, params IPrivateKeyFile[] keyFiles)
: this(host, DefaultPort, username, proxyType, proxyHost, proxyPort, proxyUsername, string.Empty, keyFiles)
{
}
Expand All @@ -116,7 +116,7 @@ public PrivateKeyConnectionInfo(string host, string username, ProxyTypes proxyTy
/// <param name="proxyUsername">The proxy username.</param>
/// <param name="proxyPassword">The proxy password.</param>
/// <param name="keyFiles">The key files.</param>
public PrivateKeyConnectionInfo(string host, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, string proxyPassword, params PrivateKeyFile[] keyFiles)
public PrivateKeyConnectionInfo(string host, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, string proxyPassword, params IPrivateKeyFile[] keyFiles)
: this(host, DefaultPort, username, proxyType, proxyHost, proxyPort, proxyUsername, proxyPassword, keyFiles)
{
}
Expand All @@ -133,10 +133,10 @@ public PrivateKeyConnectionInfo(string host, string username, ProxyTypes proxyTy
/// <param name="proxyUsername">The proxy username.</param>
/// <param name="proxyPassword">The proxy password.</param>
/// <param name="keyFiles">The key files.</param>
public PrivateKeyConnectionInfo(string host, int port, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, string proxyPassword, params PrivateKeyFile[] keyFiles)
public PrivateKeyConnectionInfo(string host, int port, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, string proxyPassword, params IPrivateKeyFile[] keyFiles)
: base(host, port, username, proxyType, proxyHost, proxyPort, proxyUsername, proxyPassword, new PrivateKeyAuthenticationMethod(username, keyFiles))
{
KeyFiles = new Collection<PrivateKeyFile>(keyFiles);
KeyFiles = new Collection<IPrivateKeyFile>(keyFiles);
}

#region IDisposable Members
Expand Down
28 changes: 18 additions & 10 deletions src/Renci.SshNet/PrivateKeyFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ namespace Renci.SshNet
/// </list>
/// </para>
/// </remarks>
public class PrivateKeyFile : IDisposable
public class PrivateKeyFile : IPrivateKeyFile, IDisposable
{
private static readonly Regex PrivateKeyRegex = new Regex(@"^-+ *BEGIN (?<keyName>\w+( \w+)*) PRIVATE KEY *-+\r?\n((Proc-Type: 4,ENCRYPTED\r?\nDEK-Info: (?<cipherName>[A-Z0-9-]+),(?<salt>[A-F0-9]+)\r?\n\r?\n)|(Comment: ""?[^\r\n]*""?\r?\n))?(?<data>([a-zA-Z0-9/+=]{1,80}\r?\n)+)-+ *END \k<keyName> PRIVATE KEY *-+",
#if FEATURE_REGEX_COMPILE
Expand All @@ -74,18 +74,26 @@ public class PrivateKeyFile : IDisposable

private Key _key;

private HostAlgorithm _hostKey;

/// <summary>
/// Gets the host key.
/// </summary>
public HostAlgorithm HostKey { get; private set; }
public HostAlgorithm HostKey
{
get
{
return _hostKey;
}
}

/// <summary>
/// Initializes a new instance of the <see cref="PrivateKeyFile"/> class.
/// </summary>
/// <param name="key">The key.</param>
public PrivateKeyFile(Key key)
{
HostKey = new KeyHostAlgorithm(key.ToString(), key);
_hostKey = new KeyHostAlgorithm(key.ToString(), key);
}

/// <summary>
Expand Down Expand Up @@ -215,21 +223,21 @@ private void Open(Stream privateKey, string passPhrase)
{
case "RSA":
_key = new RsaKey(decryptedData);
HostKey = new KeyHostAlgorithm("ssh-rsa", _key);
_hostKey = new KeyHostAlgorithm("ssh-rsa", _key);
break;
case "DSA":
_key = new DsaKey(decryptedData);
HostKey = new KeyHostAlgorithm("ssh-dss", _key);
_hostKey = new KeyHostAlgorithm("ssh-dss", _key);
break;
#if FEATURE_ECDSA
case "EC":
_key = new EcdsaKey(decryptedData);
HostKey = new KeyHostAlgorithm(_key.ToString(), _key);
_hostKey = new KeyHostAlgorithm(_key.ToString(), _key);
break;
#endif
case "OPENSSH":
_key = ParseOpenSshV1Key(decryptedData, passPhrase);
HostKey = new KeyHostAlgorithm(_key.ToString(), _key);
_hostKey = new KeyHostAlgorithm(_key.ToString(), _key);
break;
case "SSH2 ENCRYPTED":
var reader = new SshDataReader(decryptedData);
Expand Down Expand Up @@ -271,7 +279,7 @@ private void Open(Stream privateKey, string passPhrase)

if (decryptedLength > blobSize - 4)
throw new SshException("Invalid passphrase.");

if (keyType == "if-modn{sign{rsa-pkcs1-sha1},encrypt{rsa-pkcs1v2-oaep}}")
{
var exponent = reader.ReadBigIntWithBits();//e
Expand All @@ -281,7 +289,7 @@ private void Open(Stream privateKey, string passPhrase)
var q = reader.ReadBigIntWithBits();//p
var p = reader.ReadBigIntWithBits();//q
_key = new RsaKey(modulus, exponent, d, p, q, inverseQ);
HostKey = new KeyHostAlgorithm("ssh-rsa", _key);
_hostKey = new KeyHostAlgorithm("ssh-rsa", _key);
}
else if (keyType == "dl-modp{sign{dsa-nist-sha1},dh{plain}}")
{
Expand All @@ -296,7 +304,7 @@ private void Open(Stream privateKey, string passPhrase)
var y = reader.ReadBigIntWithBits();
var x = reader.ReadBigIntWithBits();
_key = new DsaKey(p, q, g, y, x);
HostKey = new KeyHostAlgorithm("ssh-dss", _key);
_hostKey = new KeyHostAlgorithm("ssh-dss", _key);
}
else
{
Expand Down
4 changes: 2 additions & 2 deletions src/Renci.SshNet/ScpClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ public ScpClient(string host, string username, string password)
/// <exception cref="ArgumentException"><paramref name="host"/> is invalid, -or- <paramref name="username"/> is <c>null</c> or contains only whitespace characters.</exception>
/// <exception cref="ArgumentOutOfRangeException"><paramref name="port"/> is not within <see cref="IPEndPoint.MinPort"/> and <see cref="IPEndPoint.MaxPort"/>.</exception>
[SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Justification = "Disposed in Dispose(bool) method.")]
public ScpClient(string host, int port, string username, params PrivateKeyFile[] keyFiles)
public ScpClient(string host, int port, string username, params IPrivateKeyFile[] keyFiles)
: this(new PrivateKeyConnectionInfo(host, port, username, keyFiles), true)
{
}
Expand All @@ -155,7 +155,7 @@ public ScpClient(string host, int port, string username, params PrivateKeyFile[]
/// <param name="keyFiles">Authentication private key file(s) .</param>
/// <exception cref="ArgumentNullException"><paramref name="keyFiles"/> is <c>null</c>.</exception>
/// <exception cref="ArgumentException"><paramref name="host"/> is invalid, -or- <paramref name="username"/> is <c>null</c> or contains only whitespace characters.</exception>
public ScpClient(string host, string username, params PrivateKeyFile[] keyFiles)
public ScpClient(string host, string username, params IPrivateKeyFile[] keyFiles)
: this(host, ConnectionInfo.DefaultPort, username, keyFiles)
{
}
Expand Down
10 changes: 5 additions & 5 deletions src/Renci.SshNet/SftpClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ public SftpClient(string host, string username, string password)
/// <exception cref="ArgumentException"><paramref name="host"/> is invalid. <para>-or-</para> <paramref name="username"/> is nu<b>null</b>ll or contains only whitespace characters.</exception>
/// <exception cref="ArgumentOutOfRangeException"><paramref name="port"/> is not within <see cref="IPEndPoint.MinPort"/> and <see cref="IPEndPoint.MaxPort"/>.</exception>
[SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Justification = "Disposed in Dispose(bool) method.")]
public SftpClient(string host, int port, string username, params PrivateKeyFile[] keyFiles)
public SftpClient(string host, int port, string username, params IPrivateKeyFile[] keyFiles)
: this(new PrivateKeyConnectionInfo(host, port, username, keyFiles), true)
{
}
Expand All @@ -218,7 +218,7 @@ public SftpClient(string host, int port, string username, params PrivateKeyFile[
/// <param name="keyFiles">Authentication private key file(s) .</param>
/// <exception cref="ArgumentNullException"><paramref name="keyFiles"/> is <b>null</b>.</exception>
/// <exception cref="ArgumentException"><paramref name="host"/> is invalid. <para>-or-</para> <paramref name="username"/> is <b>null</b> or contains only whitespace characters.</exception>
public SftpClient(string host, string username, params PrivateKeyFile[] keyFiles)
public SftpClient(string host, string username, params IPrivateKeyFile[] keyFiles)
: this(host, ConnectionInfo.DefaultPort, username, keyFiles)
{
}
Expand Down Expand Up @@ -592,13 +592,13 @@ public bool Exists(string path)
// using SSH_FXP_REALPATH is not an alternative as the SFTP specification has not always
// been clear on how the server should respond when the specified path is not present on
// the server:
//
//
// SSH 1 to 4:
// No mention of how the server should respond if the path is not present on the server.
//
// SSH 5:
// The server SHOULD fail the request if the path is not present on the server.
//
//
// SSH 6:
// Draft 06: The server SHOULD fail the request if the path is not present on the server.
// Draft 07 to 13: The server MUST NOT fail the request if the path does not exist.
Expand Down Expand Up @@ -627,7 +627,7 @@ public bool Exists(string path)
/// <exception cref="ArgumentException"><paramref name="path" /> is <b>null</b> or contains only whitespace characters.</exception>
/// <exception cref="SshConnectionException">Client is not connected.</exception>
/// <exception cref="SftpPermissionDeniedException">Permission to perform the operation was denied by the remote host. <para>-or-</para> A SSH command was denied by the server.</exception>
/// <exception cref="SftpPathNotFoundException"><paramref name="path"/> was not found on the remote host.</exception>///
/// <exception cref="SftpPathNotFoundException"><paramref name="path"/> was not found on the remote host.</exception>///
/// <exception cref="SshException">A SSH error where <see cref="Exception.Message" /> is the message from the remote host.</exception>
/// <exception cref="ObjectDisposedException">The method was called after the client was disposed.</exception>
/// <remarks>
Expand Down
4 changes: 2 additions & 2 deletions src/Renci.SshNet/SshClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ public SshClient(string host, string username, string password)
/// <exception cref="ArgumentException"><paramref name="host"/> is invalid, -or- <paramref name="username"/> is <c>null</c> or contains only whitespace characters.</exception>
/// <exception cref="ArgumentOutOfRangeException"><paramref name="port"/> is not within <see cref="IPEndPoint.MinPort"/> and <see cref="IPEndPoint.MaxPort"/>.</exception>
[SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Justification = "Disposed in Dispose(bool) method.")]
public SshClient(string host, int port, string username, params PrivateKeyFile[] keyFiles)
public SshClient(string host, int port, string username, params IPrivateKeyFile[] keyFiles)
: this(new PrivateKeyConnectionInfo(host, port, username, keyFiles), true)
{
}
Expand All @@ -121,7 +121,7 @@ public SshClient(string host, int port, string username, params PrivateKeyFile[]
/// </example>
/// <exception cref="ArgumentNullException"><paramref name="keyFiles"/> is <c>null</c>.</exception>
/// <exception cref="ArgumentException"><paramref name="host"/> is invalid, -or- <paramref name="username"/> is <c>null</c> or contains only whitespace characters.</exception>
public SshClient(string host, string username, params PrivateKeyFile[] keyFiles)
public SshClient(string host, string username, params IPrivateKeyFile[] keyFiles)
: this(host, ConnectionInfo.DefaultPort, username, keyFiles)
{
}
Expand Down

0 comments on commit f7fad26

Please sign in to comment.