Skip to content

Commit

Permalink
Prioritizing of encryption algorithms (might be SECURITY HOLE)
Browse files Browse the repository at this point in the history
Sending SSH certificate to client
  • Loading branch information
msvprogs committed Jul 24, 2019
1 parent 71a1c07 commit 97c6ce7
Show file tree
Hide file tree
Showing 10 changed files with 179 additions and 60 deletions.
8 changes: 7 additions & 1 deletion src/Renci.SshNet.NET35/Renci.SshNet.NET35.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,9 @@
<Compile Include="..\Renci.SshNet\PasswordConnectionInfo.cs">
<Link>PasswordConnectionInfo.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet\PriorityString.cs">
<Link>PriorityString.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet\PrivateKeyAuthenticationMethod.cs">
<Link>PrivateKeyAuthenticationMethod.cs</Link>
</Compile>
Expand Down Expand Up @@ -605,6 +608,9 @@
<Compile Include="..\Renci.SshNet\Security\CertificateHostAlgorithm.cs">
<Link>Security\CertificateHostAlgorithm.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet\Security\CertificateKeyHostAlgorithm.cs">
<Link>Security\CertificateKeyHostAlgorithm.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet\Security\Cryptography\AsymmetricCipher.cs">
<Link>Security\Cryptography\AsymmetricCipher.cs</Link>
</Compile>
Expand Down Expand Up @@ -974,7 +980,7 @@
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<ProjectExtensions>
<VisualStudio>
<UserProperties ProjectLinkReference="2f5f8c90-0bd1-424f-997c-7bc6280919d1" ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" />
<UserProperties ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" ProjectLinkReference="2f5f8c90-0bd1-424f-997c-7bc6280919d1" />
</VisualStudio>
</ProjectExtensions>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Expand Down
5 changes: 4 additions & 1 deletion src/Renci.SshNet.Tests/Classes/SessionTest_ConnectedBase.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography;
Expand Down Expand Up @@ -152,7 +153,9 @@ private void SetupMocks()
{
_serviceFactoryMock.Setup(
p =>
p.CreateKeyExchange(ConnectionInfo.KeyExchangeAlgorithms, new[] { _keyExchangeAlgorithm })).Returns(_keyExchangeMock.Object);
p.CreateKeyExchange(ConnectionInfo.KeyExchangeAlgorithms
.ToDictionary(x => x.Key.Value, x => x.Value),
new[] { _keyExchangeAlgorithm })).Returns(_keyExchangeMock.Object);
_keyExchangeMock.Setup(p => p.Name).Returns(_keyExchangeAlgorithm);
_keyExchangeMock.Setup(p => p.Start(Session, It.IsAny<KeyExchangeInitMessage>()));
_keyExchangeMock.Setup(p => p.ExchangeHash).Returns(SessionId);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography;
Expand Down Expand Up @@ -136,7 +137,8 @@ private void SetupMocks()
{
_serviceFactoryMock.Setup(
p =>
p.CreateKeyExchange(ConnectionInfo.KeyExchangeAlgorithms, new[] { _keyExchangeAlgorithm })).Returns(_keyExchangeMock.Object);
p.CreateKeyExchange(ConnectionInfo.KeyExchangeAlgorithms.ToDictionary(x => x.Key.Value, x => x.Value),
new[] { _keyExchangeAlgorithm })).Returns(_keyExchangeMock.Object);
_keyExchangeMock.Setup(p => p.Name).Returns(_keyExchangeAlgorithm);
_keyExchangeMock.Setup(p => p.Start(Session, It.IsAny<KeyExchangeInitMessage>()));
_keyExchangeMock.Setup(p => p.ExchangeHash).Returns(SessionId);
Expand Down
82 changes: 41 additions & 41 deletions src/Renci.SshNet/ConnectionInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,22 +43,22 @@ public class ConnectionInfo : IConnectionInfoInternal
/// <summary>
/// Gets supported key exchange algorithms for this connection.
/// </summary>
public IDictionary<string, Type> KeyExchangeAlgorithms { get; private set; }
public IDictionary<PriorityString, Type> KeyExchangeAlgorithms { get; private set; }

/// <summary>
/// Gets supported encryptions for this connection.
/// </summary>
public IDictionary<string, CipherInfo> Encryptions { get; private set; }
public IDictionary<PriorityString, CipherInfo> Encryptions { get; private set; }

/// <summary>
/// Gets supported hash algorithms for this connection.
/// </summary>
public IDictionary<string, HashInfo> HmacAlgorithms { get; private set; }
public IDictionary<PriorityString, HashInfo> HmacAlgorithms { get; private set; }

/// <summary>
/// Gets supported host key algorithms for this connection.
/// </summary>
public IDictionary<string, Func<byte[], KeyHostAlgorithm>> HostKeyAlgorithms { get; private set; }
public IDictionary<PriorityString, Func<byte[], KeyHostAlgorithm>> HostKeyAlgorithms { get; private set; }

/// <summary>
/// Gets supported authentication methods for this connection.
Expand Down Expand Up @@ -321,12 +321,12 @@ public ConnectionInfo(string host, int port, string username, ProxyTypes proxyTy
MaxSessions = 10;
Encoding = Encoding.UTF8;

KeyExchangeAlgorithms = new Dictionary<string, Type>
KeyExchangeAlgorithms = new Dictionary<PriorityString, Type>
{
{"diffie-hellman-group-exchange-sha256", typeof (KeyExchangeDiffieHellmanGroupExchangeSha256)},
{"diffie-hellman-group-exchange-sha1", typeof (KeyExchangeDiffieHellmanGroupExchangeSha1)},
{"diffie-hellman-group14-sha1", typeof (KeyExchangeDiffieHellmanGroup14Sha1)},
{"diffie-hellman-group1-sha1", typeof (KeyExchangeDiffieHellmanGroup1Sha1)},
{new PriorityString("diffie-hellman-group-exchange-sha256", 10), typeof (KeyExchangeDiffieHellmanGroupExchangeSha256)},
{new PriorityString("diffie-hellman-group-exchange-sha1", 5), typeof (KeyExchangeDiffieHellmanGroupExchangeSha1)},
{new PriorityString("diffie-hellman-group14-sha1", 1), typeof (KeyExchangeDiffieHellmanGroup14Sha1)},
{new PriorityString("diffie-hellman-group1-sha1", 1), typeof (KeyExchangeDiffieHellmanGroup1Sha1)},
//{"ecdh-sha2-nistp256", typeof(KeyExchangeEllipticCurveDiffieHellman)},
//{"ecdh-sha2-nistp256", typeof(...)},
//{"ecdh-sha2-nistp384", typeof(...)},
Expand All @@ -335,52 +335,52 @@ public ConnectionInfo(string host, int port, string username, ProxyTypes proxyTy
//"gss-gex-sha1-toWM5Slw5Ew8Mqkay+al2g==" - WinSSHD
};

Encryptions = new Dictionary<string, CipherInfo>
Encryptions = new Dictionary<PriorityString, CipherInfo>
{
{"aes256-ctr", new CipherInfo(256, (key, iv) => new AesCipher(key, new CtrCipherMode(iv), null))},
{"3des-cbc", new CipherInfo(192, (key, iv) => new TripleDesCipher(key, new CbcCipherMode(iv), null))},
{"aes128-cbc", new CipherInfo(128, (key, iv) => new AesCipher(key, new CbcCipherMode(iv), null))},
{"aes192-cbc", new CipherInfo(192, (key, iv) => new AesCipher(key, new CbcCipherMode(iv), null))},
{"aes256-cbc", new CipherInfo(256, (key, iv) => new AesCipher(key, new CbcCipherMode(iv), null))},
{"blowfish-cbc", new CipherInfo(128, (key, iv) => new BlowfishCipher(key, new CbcCipherMode(iv), null))},
{"twofish-cbc", new CipherInfo(256, (key, iv) => new TwofishCipher(key, new CbcCipherMode(iv), null))},
{"twofish192-cbc", new CipherInfo(192, (key, iv) => new TwofishCipher(key, new CbcCipherMode(iv), null))},
{"twofish128-cbc", new CipherInfo(128, (key, iv) => new TwofishCipher(key, new CbcCipherMode(iv), null))},
{"twofish256-cbc", new CipherInfo(256, (key, iv) => new TwofishCipher(key, new CbcCipherMode(iv), null))},
{new PriorityString("aes256-ctr", 100), new CipherInfo(256, (key, iv) => new AesCipher(key, new CtrCipherMode(iv), null))},
{new PriorityString("3des-cbc", 10), new CipherInfo(192, (key, iv) => new TripleDesCipher(key, new CbcCipherMode(iv), null))},
{new PriorityString("aes128-cbc", 90), new CipherInfo(128, (key, iv) => new AesCipher(key, new CbcCipherMode(iv), null))},
{new PriorityString("aes192-cbc", 91), new CipherInfo(192, (key, iv) => new AesCipher(key, new CbcCipherMode(iv), null))},
{new PriorityString("aes256-cbc", 92), new CipherInfo(256, (key, iv) => new AesCipher(key, new CbcCipherMode(iv), null))},
{new PriorityString("blowfish-cbc", 80), new CipherInfo(128, (key, iv) => new BlowfishCipher(key, new CbcCipherMode(iv), null))},
{new PriorityString("twofish-cbc", 70), new CipherInfo(256, (key, iv) => new TwofishCipher(key, new CbcCipherMode(iv), null))},
{new PriorityString("twofish192-cbc", 71), new CipherInfo(192, (key, iv) => new TwofishCipher(key, new CbcCipherMode(iv), null))},
{new PriorityString("twofish128-cbc", 72), new CipherInfo(128, (key, iv) => new TwofishCipher(key, new CbcCipherMode(iv), null))},
{new PriorityString("twofish256-cbc", 73), new CipherInfo(256, (key, iv) => new TwofishCipher(key, new CbcCipherMode(iv), null))},
////{"serpent256-cbc", typeof(CipherSerpent256CBC)},
////{"serpent192-cbc", typeof(...)},
////{"serpent128-cbc", typeof(...)},
{"arcfour", new CipherInfo(128, (key, iv) => new Arc4Cipher(key, false))},
{"arcfour128", new CipherInfo(128, (key, iv) => new Arc4Cipher(key, true))},
{"arcfour256", new CipherInfo(256, (key, iv) => new Arc4Cipher(key, true))},
{new PriorityString("arcfour", 50), new CipherInfo(128, (key, iv) => new Arc4Cipher(key, false))},
{new PriorityString("arcfour128", 51), new CipherInfo(128, (key, iv) => new Arc4Cipher(key, true))},
{new PriorityString("arcfour256", 52), new CipherInfo(256, (key, iv) => new Arc4Cipher(key, true))},
////{"idea-cbc", typeof(...)},
{"cast128-cbc", new CipherInfo(128, (key, iv) => new CastCipher(key, new CbcCipherMode(iv), null))},
{new PriorityString("cast128-cbc", 40), new CipherInfo(128, (key, iv) => new CastCipher(key, new CbcCipherMode(iv), null))},
////{"rijndael-cbc@lysator.liu.se", typeof(...)},
{"aes128-ctr", new CipherInfo(128, (key, iv) => new AesCipher(key, new CtrCipherMode(iv), null))},
{"aes192-ctr", new CipherInfo(192, (key, iv) => new AesCipher(key, new CtrCipherMode(iv), null))},
{new PriorityString("aes128-ctr", 98), new CipherInfo(128, (key, iv) => new AesCipher(key, new CtrCipherMode(iv), null))},
{new PriorityString("aes192-ctr", 99), new CipherInfo(192, (key, iv) => new AesCipher(key, new CtrCipherMode(iv), null))},
};

HmacAlgorithms = new Dictionary<string, HashInfo>
HmacAlgorithms = new Dictionary<PriorityString, HashInfo>
{
{"hmac-md5", new HashInfo(16*8, CryptoAbstraction.CreateHMACMD5)},
{"hmac-md5-96", new HashInfo(16*8, key => CryptoAbstraction.CreateHMACMD5(key, 96))},
{"hmac-sha1", new HashInfo(20*8, CryptoAbstraction.CreateHMACSHA1)},
{"hmac-sha1-96", new HashInfo(20*8, key => CryptoAbstraction.CreateHMACSHA1(key, 96))},
{"hmac-sha2-256", new HashInfo(32*8, CryptoAbstraction.CreateHMACSHA256)},
{"hmac-sha2-256-96", new HashInfo(32*8, key => CryptoAbstraction.CreateHMACSHA256(key, 96))},
{"hmac-sha2-512", new HashInfo(64 * 8, CryptoAbstraction.CreateHMACSHA512)},
{"hmac-sha2-512-96", new HashInfo(64 * 8, key => CryptoAbstraction.CreateHMACSHA512(key, 96))},
{new PriorityString("hmac-md5", 1), new HashInfo(16*8, CryptoAbstraction.CreateHMACMD5)},
{new PriorityString("hmac-md5-96", 0), new HashInfo(16*8, key => CryptoAbstraction.CreateHMACMD5(key, 96))},
{new PriorityString("hmac-sha1", 50), new HashInfo(20*8, CryptoAbstraction.CreateHMACSHA1)},
{new PriorityString("hmac-sha1-96", 49), new HashInfo(20*8, key => CryptoAbstraction.CreateHMACSHA1(key, 96))},
{new PriorityString("hmac-sha2-256", 100), new HashInfo(32*8, CryptoAbstraction.CreateHMACSHA256)},
{new PriorityString("hmac-sha2-256-96", 99), new HashInfo(32*8, key => CryptoAbstraction.CreateHMACSHA256(key, 96))},
{new PriorityString("hmac-sha2-512", 100), new HashInfo(64 * 8, CryptoAbstraction.CreateHMACSHA512)},
{new PriorityString("hmac-sha2-512-96", 99), new HashInfo(64 * 8, key => CryptoAbstraction.CreateHMACSHA512(key, 96))},
//{"umac-64@openssh.com", typeof(HMacSha1)},
{"hmac-ripemd160", new HashInfo(160, CryptoAbstraction.CreateHMACRIPEMD160)},
{"hmac-ripemd160@openssh.com", new HashInfo(160, CryptoAbstraction.CreateHMACRIPEMD160)},
{new PriorityString("hmac-ripemd160", 40), new HashInfo(160, CryptoAbstraction.CreateHMACRIPEMD160)},
{new PriorityString("hmac-ripemd160@openssh.com", 40), new HashInfo(160, CryptoAbstraction.CreateHMACRIPEMD160)},
//{"none", typeof(...)},
};

HostKeyAlgorithms = new Dictionary<string, Func<byte[], KeyHostAlgorithm>>
HostKeyAlgorithms = new Dictionary<PriorityString, Func<byte[], KeyHostAlgorithm>>
{
{"ssh-rsa", data => new KeyHostAlgorithm("ssh-rsa", new RsaKey(), data, 2)},
{"ssh-dss", data => new KeyHostAlgorithm("ssh-dss", new DsaKey(), data, int.MaxValue)},
{"ssh-rsa-cert-v01@openssh.com", data => new KeyHostAlgorithm("ssh-rsa-cert-v01@openssh.com", new RsaCertV01Key(), data, 3)}
{new PriorityString("ssh-rsa", 50), data => new KeyHostAlgorithm("ssh-rsa", new RsaKey(), data, 2)},
{new PriorityString("ssh-dss", 49), data => new KeyHostAlgorithm("ssh-dss", new DsaKey(), data, int.MaxValue)},
{new PriorityString("ssh-rsa-cert-v01@openssh.com", 100), data => new CertificateKeyHostAlgorithm("ssh-rsa-cert-v01@openssh.com", new RsaCertV01Key(), data, 3)}
//{"ecdsa-sha2-nistp256 "}
//{"x509v3-sign-rsa", () => { ... },
//{"x509v3-sign-dss", () => { ... },
Expand Down
77 changes: 77 additions & 0 deletions src/Renci.SshNet/PriorityString.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
using System;

namespace Renci.SshNet
{
/// <summary>
///
/// </summary>
public sealed class PriorityString : IEquatable<PriorityString>
{
/// <summary>
///
/// </summary>
public string Value { get; private set; }

/// <summary>
///
/// </summary>
public int Priority { get; private set; }

/// <summary>
///
/// </summary>
/// <param name="value"></param>
/// <param name="priority"></param>
public PriorityString(string value, int priority)
{
Value = value;
Priority = priority;
}

/// <summary>
///
/// </summary>
/// <param name="other"></param>
/// <returns></returns>
public bool Equals(PriorityString other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return string.Equals(Value, other.Value) && Priority == other.Priority;
}

/// <summary>
///
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
return obj is PriorityString && Equals((PriorityString) obj);
}

/// <summary>
///
/// </summary>
/// <returns></returns>
public override int GetHashCode()
{
unchecked
{
return ((Value != null ? Value.GetHashCode() : 0) * 397) ^ Priority;
}
}

/// <summary>
///
/// </summary>
/// <param name="src"></param>
/// <returns></returns>
public static implicit operator PriorityString(string src)
{
return new PriorityString(src, 0);
}
}
}
2 changes: 2 additions & 0 deletions src/Renci.SshNet/Renci.SshNet.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -164,10 +164,12 @@
<Compile Include="Messages\Transport\KeyExchangeEcdhInitMessage.cs" />
<Compile Include="Messages\Transport\KeyExchangeEcdhReplyMessage.cs" />
<Compile Include="Netconf\INetConfSession.cs" />
<Compile Include="PriorityString.cs" />
<Compile Include="RemotePathDoubleQuoteTransformation.cs" />
<Compile Include="RemotePathNoneTransformation.cs" />
<Compile Include="RemotePathShellQuoteTransformation.cs" />
<Compile Include="RemotePathTransformation.cs" />
<Compile Include="Security\CertificateKeyHostAlgorithm.cs" />
<Compile Include="Security\Cryptography\HMACMD5.cs" />
<Compile Include="Security\Cryptography\HMACSHA1.cs" />
<Compile Include="Security\Cryptography\HMACSHA256.cs" />
Expand Down
27 changes: 27 additions & 0 deletions src/Renci.SshNet/Security/CertificateKeyHostAlgorithm.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
namespace Renci.SshNet.Security
{
/// <inheritdoc />
public class CertificateKeyHostAlgorithm : KeyHostAlgorithm
{
private readonly byte[] _data;

/// <inheritdoc />
public override byte[] Data
{
get { return _data; }
}

/// <inheritdoc />
public CertificateKeyHostAlgorithm(string name, Key key)
: base(name, key)
{
}

/// <inheritdoc />
public CertificateKeyHostAlgorithm(string name, Key key, byte[] data, int maxKeyFields)
: base(name, key, data, maxKeyFields)
{
_data = data;
}
}
}
Loading

0 comments on commit 97c6ce7

Please sign in to comment.