Skip to content

Commit 1f356b4

Browse files
authored
Allow empty softwareversion string (#822) (#1441)
Co-authored-by: Martin Dörig <[email protected]>
1 parent ffd43da commit 1f356b4

File tree

2 files changed

+124
-1
lines changed

2 files changed

+124
-1
lines changed

src/Renci.SshNet/Connection/ProtocolVersionExchange.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ namespace Renci.SshNet.Connection
2222
internal sealed partial class ProtocolVersionExchange : IProtocolVersionExchange
2323
{
2424
private const byte Null = 0x00;
25-
private const string ServerVersionPattern = "^SSH-(?<protoversion>[^-]+)-(?<softwareversion>.+?)([ ](?<comments>.+))?$";
25+
private const string ServerVersionPattern = "^SSH-(?<protoversion>[^-]+)-(?<softwareversion>.*?)([ ](?<comments>.+))?$";
2626

2727
#if NET7_0_OR_GREATER
2828
private static readonly Regex ServerVersionRegex = GetServerVersionRegex();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Net;
5+
using System.Net.Sockets;
6+
using System.Text;
7+
using System.Threading;
8+
9+
using Microsoft.VisualStudio.TestTools.UnitTesting;
10+
11+
using Renci.SshNet.Common;
12+
using Renci.SshNet.Connection;
13+
using Renci.SshNet.Tests.Common;
14+
15+
namespace Renci.SshNet.Tests.Classes.Connection
16+
{
17+
[TestClass]
18+
public class ProtocolVersionExchangeTest_ServerResponseValid_EmptySoftwareVersion
19+
{
20+
private AsyncSocketListener _server;
21+
private ProtocolVersionExchange _protocolVersionExchange;
22+
private string _clientVersion;
23+
private TimeSpan _timeout;
24+
private IPEndPoint _serverEndPoint;
25+
private List<byte> _dataReceivedByServer;
26+
private byte[] _serverIdentification;
27+
private bool _clientDisconnected;
28+
private Socket _client;
29+
private SshIdentification _actual;
30+
31+
[TestInitialize]
32+
public void Setup()
33+
{
34+
Arrange();
35+
Act();
36+
}
37+
38+
[TestCleanup]
39+
public void Cleanup()
40+
{
41+
if (_server != null)
42+
{
43+
_server.Dispose();
44+
_server = null;
45+
}
46+
47+
if (_client != null)
48+
{
49+
_client.Shutdown(SocketShutdown.Both);
50+
_client.Close();
51+
_client = null;
52+
}
53+
}
54+
55+
protected void Arrange()
56+
{
57+
_clientVersion = "SSH-2.0-Renci.SshNet.SshClient.0.0.1";
58+
_timeout = TimeSpan.FromSeconds(5);
59+
_serverEndPoint = new IPEndPoint(IPAddress.Loopback, 8122);
60+
_dataReceivedByServer = new List<byte>();
61+
_serverIdentification = Encoding.UTF8.GetBytes("SSH-78.5-\r\n");
62+
63+
_server = new AsyncSocketListener(_serverEndPoint);
64+
_server.Start();
65+
_server.BytesReceived += (bytes, socket) =>
66+
{
67+
_dataReceivedByServer.AddRange(bytes);
68+
69+
_ = socket.Send(_serverIdentification);
70+
71+
socket.Shutdown(SocketShutdown.Send);
72+
};
73+
_server.Disconnected += (socket) => _clientDisconnected = true;
74+
75+
_client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
76+
_client.Connect(_serverEndPoint);
77+
78+
_protocolVersionExchange = new ProtocolVersionExchange();
79+
}
80+
81+
protected void Act()
82+
{
83+
_actual = _protocolVersionExchange.Start(_clientVersion, _client, _timeout);
84+
85+
// Give some time to process all messages
86+
Thread.Sleep(200);
87+
}
88+
89+
[TestMethod]
90+
public void StartShouldReturnIdentificationOfServer()
91+
{
92+
Assert.IsNotNull(_actual);
93+
Assert.AreEqual("78.5", _actual.ProtocolVersion);
94+
Assert.AreEqual(string.Empty, _actual.SoftwareVersion);
95+
Assert.IsNull(_actual.Comments);
96+
}
97+
98+
[TestMethod]
99+
public void ClientIdentificationWasSentToServer()
100+
{
101+
var expected = Encoding.UTF8.GetBytes(_clientVersion);
102+
103+
Assert.AreEqual(expected.Length + 2, _dataReceivedByServer.Count);
104+
105+
Assert.IsTrue(expected.SequenceEqual(_dataReceivedByServer.Take(expected.Length)));
106+
Assert.AreEqual(Session.CarriageReturn, _dataReceivedByServer[_dataReceivedByServer.Count - 2]);
107+
Assert.AreEqual(Session.LineFeed, _dataReceivedByServer[_dataReceivedByServer.Count - 1]);
108+
}
109+
110+
[TestMethod]
111+
public void ConnectionIsClosedByServer()
112+
{
113+
Assert.IsTrue(_client.Connected);
114+
Assert.IsFalse(_clientDisconnected);
115+
116+
var bytesReceived = _client.Receive(new byte[1]);
117+
Assert.AreEqual(0, bytesReceived);
118+
119+
Assert.IsTrue(_client.Connected);
120+
Assert.IsFalse(_clientDisconnected);
121+
}
122+
}
123+
}

0 commit comments

Comments
 (0)