From 07c2a6001fc26a758cd3c4abadb10d851847f84e Mon Sep 17 00:00:00 2001 From: drieseng Date: Sun, 31 Jul 2016 11:38:58 +0200 Subject: [PATCH 1/4] Code formatting. --- src/Renci.SshNet/Security/KeyExchangeDiffieHellman.cs | 7 ++----- .../Security/KeyExchangeDiffieHellmanGroupSha1.cs | 2 -- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/Renci.SshNet/Security/KeyExchangeDiffieHellman.cs b/src/Renci.SshNet/Security/KeyExchangeDiffieHellman.cs index 63d4ffa4..79c84c29 100644 --- a/src/Renci.SshNet/Security/KeyExchangeDiffieHellman.cs +++ b/src/Renci.SshNet/Security/KeyExchangeDiffieHellman.cs @@ -65,17 +65,14 @@ namespace Renci.SshNet.Security { var exchangeHash = CalculateHash(); - var length = (uint)(_hostKey[0] << 24 | _hostKey[1] << 16 | _hostKey[2] << 8 | _hostKey[3]); - + var length = (uint) (_hostKey[0] << 24 | _hostKey[1] << 16 | _hostKey[2] << 8 | _hostKey[3]); var algorithmName = Encoding.UTF8.GetString(_hostKey, 4, (int)length); - var key = Session.ConnectionInfo.HostKeyAlgorithms[algorithmName](_hostKey); Session.ConnectionInfo.CurrentHostKeyAlgorithm = algorithmName; if (CanTrustHostKey(key)) { - return key.VerifySignature(exchangeHash, _signature); } return false; @@ -113,7 +110,7 @@ namespace Renci.SshNet.Security _clientExchangeValue = BigInteger.ModPow(_group, _randomValue, _prime); - } while (_clientExchangeValue < 1 || _clientExchangeValue > ((_prime - 1))); + } while (_clientExchangeValue < 1 || _clientExchangeValue > (_prime - 1)); } /// diff --git a/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupSha1.cs b/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupSha1.cs index bb32193b..d4a9b016 100644 --- a/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupSha1.cs +++ b/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupSha1.cs @@ -55,13 +55,11 @@ namespace Renci.SshNet.Security Session.MessageReceived += Session_MessageReceived; _prime = GroupPrime; - _group = new BigInteger(new byte[] { 2 }); PopulateClientExchangeValue(); SendMessage(new KeyExchangeDhInitMessage(_clientExchangeValue)); - } /// From 7e2836a7a7833ddb068e3aa7dd07470ffc9e18e8 Mon Sep 17 00:00:00 2001 From: drieseng Date: Sun, 31 Jul 2016 11:39:26 +0200 Subject: [PATCH 2/4] Modify TryAuthenticate to static. --- src/Renci.SshNet/ClientAuthentication.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Renci.SshNet/ClientAuthentication.cs b/src/Renci.SshNet/ClientAuthentication.cs index f64faf86..b626bce0 100644 --- a/src/Renci.SshNet/ClientAuthentication.cs +++ b/src/Renci.SshNet/ClientAuthentication.cs @@ -46,10 +46,10 @@ namespace Renci.SshNet } - private bool TryAuthenticate(ISession session, - AuthenticationState authenticationState, - ICollection allowedAuthenticationMethods, - ref SshAuthenticationException authenticationException) + private static bool TryAuthenticate(ISession session, + AuthenticationState authenticationState, + ICollection allowedAuthenticationMethods, + ref SshAuthenticationException authenticationException) { if (allowedAuthenticationMethods.Count == 0) { From c5d51b9d9d1bfc2ddefe606654f2d9a9d1f94f87 Mon Sep 17 00:00:00 2001 From: drieseng Date: Sun, 31 Jul 2016 11:45:31 +0200 Subject: [PATCH 3/4] Harden against "leaking" message registration. Fixes issue #55. --- ...KeyboardInteractiveAuthenticationMethod.cs | 5 +- .../PasswordAuthenticationMethod.cs | 1 + .../PrivateKeyAuthenticationMethod.cs | 91 ++++++++++--------- ...changeDiffieHellmanGroupExchangeShaBase.cs | 33 ++++--- 4 files changed, 72 insertions(+), 58 deletions(-) diff --git a/src/Renci.SshNet/KeyboardInteractiveAuthenticationMethod.cs b/src/Renci.SshNet/KeyboardInteractiveAuthenticationMethod.cs index 88ca3bf5..ba272362 100644 --- a/src/Renci.SshNet/KeyboardInteractiveAuthenticationMethod.cs +++ b/src/Renci.SshNet/KeyboardInteractiveAuthenticationMethod.cs @@ -57,15 +57,16 @@ namespace Renci.SshNet session.UserAuthenticationFailureReceived += Session_UserAuthenticationFailureReceived; session.MessageReceived += Session_MessageReceived; + session.RegisterMessage("SSH_MSG_USERAUTH_INFO_REQUEST"); + try { - session.RegisterMessage("SSH_MSG_USERAUTH_INFO_REQUEST"); session.SendMessage(_requestMessage); session.WaitOnHandle(_authenticationCompleted); - session.UnRegisterMessage("SSH_MSG_USERAUTH_INFO_REQUEST"); } finally { + session.UnRegisterMessage("SSH_MSG_USERAUTH_INFO_REQUEST"); session.UserAuthenticationSuccessReceived -= Session_UserAuthenticationSuccessReceived; session.UserAuthenticationFailureReceived -= Session_UserAuthenticationFailureReceived; session.MessageReceived -= Session_MessageReceived; diff --git a/src/Renci.SshNet/PasswordAuthenticationMethod.cs b/src/Renci.SshNet/PasswordAuthenticationMethod.cs index c66c6ae5..d4dd45d2 100644 --- a/src/Renci.SshNet/PasswordAuthenticationMethod.cs +++ b/src/Renci.SshNet/PasswordAuthenticationMethod.cs @@ -89,6 +89,7 @@ namespace Renci.SshNet } finally { + session.UnRegisterMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ"); session.UserAuthenticationSuccessReceived -= Session_UserAuthenticationSuccessReceived; session.UserAuthenticationFailureReceived -= Session_UserAuthenticationFailureReceived; session.MessageReceived -= Session_MessageReceived; diff --git a/src/Renci.SshNet/PrivateKeyAuthenticationMethod.cs b/src/Renci.SshNet/PrivateKeyAuthenticationMethod.cs index 966e4a76..effb7773 100644 --- a/src/Renci.SshNet/PrivateKeyAuthenticationMethod.cs +++ b/src/Renci.SshNet/PrivateKeyAuthenticationMethod.cs @@ -60,55 +60,65 @@ namespace Renci.SshNet session.RegisterMessage("SSH_MSG_USERAUTH_PK_OK"); - foreach (var keyFile in KeyFiles) + try { - _authenticationCompleted.Reset(); - _isSignatureRequired = false; - - var message = new RequestMessagePublicKey(ServiceName.Connection, Username, keyFile.HostKey.Name, keyFile.HostKey.Data); - - if (KeyFiles.Count < 2) - { - // If only one key file provided then send signature for very first request - var signatureData = new SignatureData(message, session.SessionId).GetBytes(); - - message.Signature = keyFile.HostKey.Sign(signatureData); - } - - // Send public key authentication request - session.SendMessage(message); - - session.WaitOnHandle(_authenticationCompleted); - - if (_isSignatureRequired) + foreach (var keyFile in KeyFiles) { _authenticationCompleted.Reset(); + _isSignatureRequired = false; - var signatureMessage = new RequestMessagePublicKey(ServiceName.Connection, Username, keyFile.HostKey.Name, keyFile.HostKey.Data); + var message = new RequestMessagePublicKey(ServiceName.Connection, + Username, + keyFile.HostKey.Name, + keyFile.HostKey.Data); - var signatureData = new SignatureData(message, session.SessionId).GetBytes(); + if (KeyFiles.Count < 2) + { + // If only one key file provided then send signature for very first request + var signatureData = new SignatureData(message, session.SessionId).GetBytes(); - signatureMessage.Signature = keyFile.HostKey.Sign(signatureData); + message.Signature = keyFile.HostKey.Sign(signatureData); + } - // Send public key authentication request with signature - session.SendMessage(signatureMessage); + // Send public key authentication request + session.SendMessage(message); + + session.WaitOnHandle(_authenticationCompleted); + + if (_isSignatureRequired) + { + _authenticationCompleted.Reset(); + + var signatureMessage = new RequestMessagePublicKey(ServiceName.Connection, + Username, + keyFile.HostKey.Name, + keyFile.HostKey.Data); + + var signatureData = new SignatureData(message, session.SessionId).GetBytes(); + + signatureMessage.Signature = keyFile.HostKey.Sign(signatureData); + + // Send public key authentication request with signature + session.SendMessage(signatureMessage); + } + + session.WaitOnHandle(_authenticationCompleted); + + if (_authenticationResult == AuthenticationResult.Success) + { + break; + } } - session.WaitOnHandle(_authenticationCompleted); - - if (_authenticationResult == AuthenticationResult.Success) - { - break; - } + return _authenticationResult; + } + finally + { + session.UserAuthenticationSuccessReceived -= Session_UserAuthenticationSuccessReceived; + session.UserAuthenticationFailureReceived -= Session_UserAuthenticationFailureReceived; + session.MessageReceived -= Session_MessageReceived; + session.UnRegisterMessage("SSH_MSG_USERAUTH_PK_OK"); } - - session.UserAuthenticationSuccessReceived -= Session_UserAuthenticationSuccessReceived; - session.UserAuthenticationFailureReceived -= Session_UserAuthenticationFailureReceived; - session.MessageReceived -= Session_MessageReceived; - - session.UnRegisterMessage("SSH_MSG_USERAUTH_PK_OK"); - - return _authenticationResult; } private void Session_UserAuthenticationSuccessReceived(object sender, MessageEventArgs e) @@ -168,8 +178,8 @@ namespace Renci.SshNet var authenticationCompleted = _authenticationCompleted; if (authenticationCompleted != null) { - authenticationCompleted.Dispose(); _authenticationCompleted = null; + authenticationCompleted.Dispose(); } _isDisposed = true; @@ -243,6 +253,5 @@ namespace Renci.SshNet WriteBinaryString(_message.PublicKeyData); } } - } } diff --git a/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupExchangeShaBase.cs b/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupExchangeShaBase.cs index 1c26e517..40543471 100644 --- a/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupExchangeShaBase.cs +++ b/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupExchangeShaBase.cs @@ -50,11 +50,10 @@ namespace Renci.SshNet.Security base.Start(session, message); Session.RegisterMessage("SSH_MSG_KEX_DH_GEX_GROUP"); - Session.RegisterMessage("SSH_MSG_KEX_DH_GEX_REPLY"); Session.MessageReceived += Session_MessageReceived; - // 1. send SSH_MSG_KEY_DH_GEX_REQUEST + // 1. client sends SSH_MSG_KEY_DH_GEX_REQUEST SendMessage(new KeyExchangeDhGroupExchangeRequest(MinimumGroupSize, PreferredGroupSize, MaximumProupSize)); } @@ -71,34 +70,38 @@ namespace Renci.SshNet.Security private void Session_MessageReceived(object sender, MessageEventArgs e) { + // 2. server sends SSH_MSG_KEX_DH_GEX_GROUP var groupMessage = e.Message as KeyExchangeDhGroupExchangeGroup; if (groupMessage != null) { - // Unregister message once received + // Unregister SSH_MSG_KEX_DH_GEX_GROUP message once received Session.UnRegisterMessage("SSH_MSG_KEX_DH_GEX_GROUP"); + // Register in order to be able to receive SSH_MSG_KEX_DH_GEX_REPLY message + Session.RegisterMessage("SSH_MSG_KEX_DH_GEX_REPLY"); - // 2. Receive SSH_MSG_KEX_DH_GEX_GROUP _prime = groupMessage.SafePrime; _group = groupMessage.SubGroup; PopulateClientExchangeValue(); - // 3. Send SSH_MSG_KEX_DH_GEX_INIT + // 3. client sends SSH_MSG_KEX_DH_GEX_INIT SendMessage(new KeyExchangeDhGroupExchangeInit(_clientExchangeValue)); + + // Skip further execution as we'll be waiting for the SSH_MSG_KEX_DH_GEX_REPLY message + return; } - else + + // 4. server sends SSH_MSG_KEX_DH_GEX_REPLY + var replyMessage = e.Message as KeyExchangeDhGroupExchangeReply; + if (replyMessage != null) { - var replyMessage = e.Message as KeyExchangeDhGroupExchangeReply; - if (replyMessage != null) - { - // Unregister message once received - Session.UnRegisterMessage("SSH_MSG_KEX_DH_GEX_REPLY"); + // Unregister SSH_MSG_KEX_DH_GEX_REPLY message once received + Session.UnRegisterMessage("SSH_MSG_KEX_DH_GEX_REPLY"); - HandleServerDhReply(replyMessage.HostKey, replyMessage.F, replyMessage.Signature); + HandleServerDhReply(replyMessage.HostKey, replyMessage.F, replyMessage.Signature); - // When SSH_MSG_KEX_DH_GEX_REPLY received key exchange is completed - Finish(); - } + // When SSH_MSG_KEX_DH_GEX_REPLY received key exchange is completed + Finish(); } } } From f4f6708f46e6ae90e2386d40610a59ae1289197d Mon Sep 17 00:00:00 2001 From: drieseng Date: Sun, 31 Jul 2016 11:45:57 +0200 Subject: [PATCH 4/4] Give in to Resharper's urge to save "migrated" settings. --- src/Renci.SshNet.VS2015.sln.DotSettings | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Renci.SshNet.VS2015.sln.DotSettings b/src/Renci.SshNet.VS2015.sln.DotSettings index 45db2ca6..15b1b217 100644 --- a/src/Renci.SshNet.VS2015.sln.DotSettings +++ b/src/Renci.SshNet.VS2015.sln.DotSettings @@ -16,4 +16,7 @@ CHOP_IF_LONG HMACMD HMACSHA + True + True + True integration,LongRunning \ No newline at end of file