diff --git a/src/Renci.SshNet/Connection/IProtocolVersionExchange.cs b/src/Renci.SshNet/Connection/IProtocolVersionExchange.cs
index c804c291f..68c3c334c 100644
--- a/src/Renci.SshNet/Connection/IProtocolVersionExchange.cs
+++ b/src/Renci.SshNet/Connection/IProtocolVersionExchange.cs
@@ -19,8 +19,22 @@ internal interface IProtocolVersionExchange
///
SshIdentification Start(string clientVersion, Socket socket, TimeSpan timeout);
+
+ ///
+ /// Performs the SSH protocol version exchange.
+ ///
+ /// The identification string of the SSH client.
+ /// A connected to the server.
+ /// The maximum time to wait for the server to respond.
+ /// Allow server to identify itself first.
+ ///
+ /// The SSH identification of the server.
+ ///
+ SshIdentification Start(string clientVersion, Socket socket, TimeSpan timeout, bool lazyIdentification);
+
#if FEATURE_TAP
System.Threading.Tasks.Task StartAsync(string clientVersion, Socket socket, System.Threading.CancellationToken cancellationToken);
#endif
+
}
}
diff --git a/src/Renci.SshNet/Connection/ProtocolVersionExchange.cs b/src/Renci.SshNet/Connection/ProtocolVersionExchange.cs
index 4e6957c10..5f41f50c2 100644
--- a/src/Renci.SshNet/Connection/ProtocolVersionExchange.cs
+++ b/src/Renci.SshNet/Connection/ProtocolVersionExchange.cs
@@ -41,9 +41,27 @@ internal class ProtocolVersionExchange : IProtocolVersionExchange
///
public SshIdentification Start(string clientVersion, Socket socket, TimeSpan timeout)
{
- // 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(clientVersion + "\x0D\x0A"));
+ return Start(clientVersion, socket, timeout, false);
+ }
+
+ ///
+ /// Performs the SSH protocol version exchange.
+ ///
+ /// The identification string of the SSH client.
+ /// A connected to the server.
+ /// The maximum time to wait for the server to respond.
+ /// Allow server to identify itself first.
+ ///
+ /// The SSH identification of the server.
+ ///
+ public SshIdentification Start(string clientVersion, Socket socket, TimeSpan timeout, bool lazyIdentification = false)
+ {
+ if (!lazyIdentification)
+ {
+ // 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(clientVersion + "\x0D\x0A"));
+ }
var bytesReceived = new List();
@@ -75,6 +93,12 @@ public SshIdentification Start(string clientVersion, Socket socket, TimeSpan tim
var identificationMatch = ServerVersionRe.Match(line);
if (identificationMatch.Success)
{
+ if (lazyIdentification)
+ {
+ // Send identification only after server identification has been validated.
+ SocketAbstraction.Send(socket, Encoding.UTF8.GetBytes(clientVersion + "\x0D\x0A"));
+ }
+
return new SshIdentification(GetGroupValue(identificationMatch, "protoversion"),
GetGroupValue(identificationMatch, "softwareversion"),
GetGroupValue(identificationMatch, "comments"));
diff --git a/src/Renci.SshNet/ConnectionInfo.cs b/src/Renci.SshNet/ConnectionInfo.cs
index af8e1ca5c..ebb0dc3ac 100644
--- a/src/Renci.SshNet/ConnectionInfo.cs
+++ b/src/Renci.SshNet/ConnectionInfo.cs
@@ -183,6 +183,14 @@ public class ConnectionInfo : IConnectionInfoInternal
///
public int MaxSessions { get; set; }
+ ///
+ /// Gets or sets if the client should identify itself later.
+ ///
+ ///
+ /// false, the default for strict RFC4253 compliance where both sides identify at the same time. true if the client should wait for the server identification.
+ ///
+ public bool LazyIdentification { get; set; }
+
///
/// Occurs when authentication banner is sent by the server.
///
@@ -432,6 +440,8 @@ public ConnectionInfo(string host, int port, string username, ProxyTypes proxyTy
ProxyPassword = proxyPassword;
AuthenticationMethods = authenticationMethods;
+
+ LazyIdentification = false;
}
///
diff --git a/src/Renci.SshNet/Session.cs b/src/Renci.SshNet/Session.cs
index 0846cb2cd..5966eeec6 100644
--- a/src/Renci.SshNet/Session.cs
+++ b/src/Renci.SshNet/Session.cs
@@ -591,7 +591,7 @@ public void Connect()
.Connect(ConnectionInfo);
var serverIdentification = _serviceFactory.CreateProtocolVersionExchange()
- .Start(ClientVersion, _socket, ConnectionInfo.Timeout);
+ .Start(ClientVersion, _socket, ConnectionInfo.Timeout, ConnectionInfo.LazyIdentification);
// Set connection versions
ServerVersion = ConnectionInfo.ServerVersion = serverIdentification.ToString();