Immediately sent identification string when connection is established.

Fixes #689.
This commit is contained in:
drieseng
2020-06-01 09:52:49 +02:00
parent ab827c2eb1
commit 4906b64e7a
2 changed files with 71 additions and 18 deletions
@@ -3,9 +3,11 @@ using System.Globalization;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Renci.SshNet.Common;
using Renci.SshNet.Messages.Transport;
using Renci.SshNet.Tests.Common;
using Renci.SshNet.Tests.Properties;
@@ -98,6 +100,53 @@ namespace Renci.SshNet.Tests.Classes
}
}
[TestMethod]
public void ConnectShouldImmediatelySendIdentificationStringWhenConnectionHasBeenEstablised()
{
var serverEndPoint = new IPEndPoint(IPAddress.Loopback, 8122);
var connectionInfo = CreateConnectionInfo(serverEndPoint, TimeSpan.FromSeconds(5));
using (var serverStub = new AsyncSocketListener(serverEndPoint))
{
serverStub.Connected += socket =>
{
var identificationBytes = new byte[2048];
var bytesReceived = socket.Receive(identificationBytes);
if (bytesReceived > 0)
{
var identificationSttring = Encoding.ASCII.GetString(identificationBytes, 0, bytesReceived);
Console.WriteLine("STRING=" + identificationSttring);
Console.WriteLine("DONE");
socket.Send(Encoding.ASCII.GetBytes("\r\n"));
socket.Send(Encoding.ASCII.GetBytes("WELCOME banner\r\n"));
socket.Send(Encoding.ASCII.GetBytes("SSH-666-SshStub\r\n"));
}
socket.Shutdown(SocketShutdown.Send);
};
serverStub.Start();
using (var session = new Session(connectionInfo, _serviceFactoryMock.Object))
{
try
{
session.Connect();
Assert.Fail();
}
catch (SshConnectionException ex)
{
Assert.IsNull(ex.InnerException);
Assert.AreEqual("Server version '666' is not supported.", ex.Message);
Assert.AreEqual("SSH-666-SshStub", connectionInfo.ServerVersion);
}
}
}
}
[TestMethod]
public void ConnectShouldSupportProtocolIdentificationStringThatDoesNotEndWithCrlf()
{
+22 -18
View File
@@ -577,14 +577,14 @@ namespace Renci.SshNet
lock (this)
{
// If connected don't connect again
// If connected don't connect again
if (IsConnected)
return;
// reset connection specific information
// Reset connection specific information
Reset();
// Build list of available messages while connecting
// Build list of available messages while connecting
_sshMessageFactory = new SshMessageFactory();
switch (ConnectionInfo.ProxyType)
@@ -606,10 +606,14 @@ namespace Renci.SshNet
break;
}
// Immediately send the identification string since the spec states both sides MUST send an identification string
// when the connection has been established
SocketAbstraction.Send(_socket, Encoding.UTF8.GetBytes(string.Format(CultureInfo.InvariantCulture, "{0}\x0D\x0A", ClientVersion)));
Match versionMatch;
// Get server version from the server,
// ignore text lines which are sent before if any
// Get server version from the server,
// ignore text lines which are sent before if any
while (true)
{
var serverVersion = SocketReadLine(_socket, ConnectionInfo.Timeout);
@@ -623,11 +627,11 @@ namespace Renci.SshNet
}
}
// Set connection versions
// Set connection versions
ConnectionInfo.ServerVersion = ServerVersion;
ConnectionInfo.ClientVersion = ClientVersion;
// Get server SSH version
// Get server SSH version
var version = versionMatch.Result("${protoversion}");
var softwareName = versionMatch.Result("${softwareversion}");
@@ -639,9 +643,7 @@ namespace Renci.SshNet
throw new SshConnectionException(string.Format(CultureInfo.CurrentCulture, "Server version '{0}' is not supported.", version), DisconnectReason.ProtocolVersionNotSupported);
}
SocketAbstraction.Send(_socket, Encoding.UTF8.GetBytes(string.Format(CultureInfo.InvariantCulture, "{0}\x0D\x0A", ClientVersion)));
// Register Transport response messages
// Register Transport response messages
RegisterMessage("SSH_MSG_DISCONNECT");
RegisterMessage("SSH_MSG_IGNORE");
RegisterMessage("SSH_MSG_UNIMPLEMENTED");
@@ -650,29 +652,29 @@ namespace Renci.SshNet
RegisterMessage("SSH_MSG_KEXINIT");
RegisterMessage("SSH_MSG_NEWKEYS");
// Some server implementations might sent this message first, prior establishing encryption algorithm
// Some server implementations might sent this message first, prior to establishing encryption algorithm
RegisterMessage("SSH_MSG_USERAUTH_BANNER");
// mark the message listener threads as started
// Mark the message listener threads as started
_messageListenerCompleted.Reset();
// Start incoming request listener
// Start incoming request listener
ThreadAbstraction.ExecuteThread(() => MessageListener());
// Wait for key exchange to be completed
// Wait for key exchange to be completed
WaitOnHandle(_keyExchangeCompletedWaitHandle);
// If sessionId is not set then its not connected
// If sessionId is not set then its not connected
if (SessionId == null)
{
Disconnect();
return;
}
// Request user authorization service
// Request user authorization service
SendMessage(new ServiceRequestMessage(ServiceName.UserAuthentication));
// Wait for service to be accepted
// Wait for service to be accepted
WaitOnHandle(_serviceAccepted);
if (string.IsNullOrEmpty(ConnectionInfo.Username))
@@ -687,7 +689,7 @@ namespace Renci.SshNet
ConnectionInfo.Authenticate(this, _serviceFactory);
_isAuthenticated = true;
// Register Connection messages
// Register Connection messages
RegisterMessage("SSH_MSG_REQUEST_SUCCESS");
RegisterMessage("SSH_MSG_REQUEST_FAILURE");
RegisterMessage("SSH_MSG_CHANNEL_OPEN_CONFIRMATION");
@@ -2003,6 +2005,8 @@ namespace Renci.SshNet
break;
}
Console.WriteLine("RECEIVED MESSAGe " + message.GetType());
// process message
message.Process(this);
}