Skip to content

Commit 3845ade

Browse files
committed
Merge branch 'develop' into dependabot/nuget/dependencies-f0d2b07915
2 parents 8f0dd29 + 41dde35 commit 3845ade

9 files changed

Lines changed: 52 additions & 84 deletions

src/Renci.SshNet/Security/Cryptography/Ciphers/AesGcmCipher.BclImpl.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public override void Decrypt(byte[] input, int cipherTextOffset, int cipherTextL
3939

4040
try
4141
{
42-
_aesGcm.Decrypt(_nonce, cipherText, tag, output.AsSpan(plainTextOffset), associatedData);
42+
_aesGcm.Decrypt(_nonce, cipherText, tag, output.AsSpan(plainTextOffset, cipherTextLength), associatedData);
4343
}
4444
catch (AuthenticationTagMismatchException ex)
4545
{

src/Renci.SshNet/Session.cs

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ public sealed class Session : ISession
200200
private Socket _socket;
201201

202202
private ArrayBuffer _receiveBuffer = new(4 * 1024);
203+
private byte[] _plaintextReceiveBuffer = new byte[4 * 1024];
203204

204205
/// <summary>
205206
/// Gets the session semaphore that controls session channels.
@@ -1319,19 +1320,24 @@ private Message ReceiveMessage(Socket socket)
13191320

13201321
// Construct buffer for holding the payload and the inbound packet sequence as we need both in order
13211322
// to generate the hash.
1322-
var data = new byte[4 + totalPacketLength - serverMacLength];
1323+
var plaintextLength = 4 + totalPacketLength - serverMacLength;
13231324

1324-
BinaryPrimitives.WriteUInt32BigEndian(data, _inboundPacketSequence);
1325+
if (_plaintextReceiveBuffer.Length < plaintextLength)
1326+
{
1327+
Array.Resize(ref _plaintextReceiveBuffer, Math.Max(plaintextLength, 2 * _plaintextReceiveBuffer.Length));
1328+
}
1329+
1330+
BinaryPrimitives.WriteUInt32BigEndian(_plaintextReceiveBuffer, _inboundPacketSequence);
13251331

1326-
plainFirstBlock.AsSpan().CopyTo(data.AsSpan(4));
1332+
plainFirstBlock.AsSpan().CopyTo(_plaintextReceiveBuffer.AsSpan(4));
13271333

13281334
if (_serverMac != null && _serverEtm)
13291335
{
13301336
// ETM mac = MAC(key, sequence_number || packet_length || encrypted_packet)
13311337

13321338
// sequence_number
13331339
_ = _serverMac.TransformBlock(
1334-
inputBuffer: data,
1340+
inputBuffer: _plaintextReceiveBuffer,
13351341
inputOffset: 0,
13361342
inputCount: 4,
13371343
outputBuffer: null,
@@ -1363,21 +1369,23 @@ private Message ReceiveMessage(Socket socket)
13631369
input: _receiveBuffer.DangerousGetUnderlyingBuffer(),
13641370
offset: _receiveBuffer.ActiveStartOffset + blockSize,
13651371
length: numberOfBytesToDecrypt,
1366-
output: data,
1372+
output: _plaintextReceiveBuffer,
13671373
outputOffset: 4 + blockSize);
13681374

13691375
Debug.Assert(numberOfBytesDecrypted == numberOfBytesToDecrypt);
13701376
}
13711377
else
13721378
{
1373-
_receiveBuffer.ActiveReadOnlySpan.Slice(blockSize, numberOfBytesToDecrypt).CopyTo(data.AsSpan(4 + blockSize));
1379+
_receiveBuffer.ActiveReadOnlySpan
1380+
.Slice(blockSize, numberOfBytesToDecrypt)
1381+
.CopyTo(_plaintextReceiveBuffer.AsSpan(4 + blockSize));
13741382
}
13751383

13761384
if (_serverMac != null && !_serverEtm)
13771385
{
13781386
// non-ETM mac = MAC(key, sequence_number || unencrypted_packet)
13791387

1380-
var clientHash = _serverMac.ComputeHash(data);
1388+
var clientHash = _serverMac.ComputeHash(_plaintextReceiveBuffer, 0, plaintextLength);
13811389

13821390
if (!CryptoAbstraction.FixedTimeEquals(clientHash, _receiveBuffer.ActiveSpan.Slice(totalPacketLength - serverMacLength, serverMacLength)))
13831391
{
@@ -1387,19 +1395,16 @@ private Message ReceiveMessage(Socket socket)
13871395

13881396
_receiveBuffer.Discard(totalPacketLength);
13891397

1390-
var paddingLength = data[inboundPacketSequenceLength + packetLengthFieldLength];
1391-
var messagePayloadLength = packetLength - paddingLength - paddingLengthFieldLength;
1392-
var messagePayloadOffset = inboundPacketSequenceLength + packetLengthFieldLength + paddingLengthFieldLength;
1398+
var paddingLength = _plaintextReceiveBuffer[inboundPacketSequenceLength + packetLengthFieldLength];
1399+
1400+
ArraySegment<byte> payload = new(
1401+
_plaintextReceiveBuffer,
1402+
offset: inboundPacketSequenceLength + packetLengthFieldLength + paddingLengthFieldLength,
1403+
count: packetLength - paddingLength - paddingLengthFieldLength);
13931404

13941405
if (_serverDecompression != null)
13951406
{
1396-
data = _serverDecompression.Decompress(data, messagePayloadOffset, messagePayloadLength);
1397-
1398-
// Data now only contains the decompressed payload, and as such the offset is reset to zero
1399-
messagePayloadOffset = 0;
1400-
1401-
// The length of the payload is now the complete decompressed content
1402-
messagePayloadLength = data.Length;
1407+
payload = new(_serverDecompression.Decompress(payload.Array, payload.Offset, payload.Count));
14031408
}
14041409

14051410
_inboundPacketSequence++;
@@ -1411,7 +1416,7 @@ private Message ReceiveMessage(Socket socket)
14111416
throw new SshConnectionException("Inbound packet sequence number is about to wrap during initial key exchange.", DisconnectReason.KeyExchangeFailed);
14121417
}
14131418

1414-
return LoadMessage(data, messagePayloadOffset, messagePayloadLength);
1419+
return LoadMessage(payload.Array, payload.Offset, payload.Count);
14151420
}
14161421

14171422
private void TrySendDisconnect(DisconnectReason reasonCode, string message)

test/Renci.SshNet.Tests/Classes/Connection/DirectConnectorTest_Connect_TimeoutConnectingToServer.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,12 @@
33
using System.Globalization;
44
using System.Net;
55
using System.Net.Sockets;
6-
using System.Runtime.InteropServices;
76

87
using Microsoft.VisualStudio.TestTools.UnitTesting;
98

109
using Moq;
1110

1211
using Renci.SshNet.Common;
13-
using Renci.SshNet.Tests.Common;
1412

1513
namespace Renci.SshNet.Tests.Classes.Connection
1614
{
@@ -72,23 +70,26 @@ protected override void Act()
7270
}
7371
}
7472

75-
[TestMethodForPlatform(nameof(OSPlatform.Windows))]
73+
[TestMethod]
74+
[OSCondition(OperatingSystems.Windows)]
7675
public void ConnectShouldHaveThrownSshOperationTimeoutExceptionOnWindows()
7776
{
7877
Assert.IsNull(_actualException.InnerException);
7978
Assert.IsInstanceOfType<SshOperationTimeoutException>(_actualException);
8079
Assert.AreEqual(string.Format(CultureInfo.InvariantCulture, "Connection failed to establish within {0} milliseconds.", _connectionInfo.Timeout.TotalMilliseconds), _actualException.Message);
8180
}
8281

83-
[TestMethodForPlatform(nameof(OSPlatform.Linux))]
82+
[TestMethod]
83+
[OSCondition(OperatingSystems.Linux)]
8484
public void ConnectShouldHaveThrownSocketExceptionOnLinux()
8585
{
8686
Assert.IsNull(_actualException.InnerException);
8787
Assert.IsInstanceOfType<SocketException>(_actualException);
8888
Assert.AreEqual("Connection refused", _actualException.Message);
8989
}
9090

91-
[TestMethodForPlatform(nameof(OSPlatform.Windows))]
91+
[TestMethod]
92+
[OSCondition(OperatingSystems.Windows)]
9293
public void ConnectShouldHaveRespectedTimeoutOnWindows()
9394
{
9495
var errorText = string.Format("Elapsed: {0}, Timeout: {1}",

test/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_TimeoutConnectingToProxy.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,12 @@
33
using System.Globalization;
44
using System.Net;
55
using System.Net.Sockets;
6-
using System.Runtime.InteropServices;
76

87
using Microsoft.VisualStudio.TestTools.UnitTesting;
98

109
using Moq;
1110

1211
using Renci.SshNet.Common;
13-
using Renci.SshNet.Tests.Common;
1412

1513
namespace Renci.SshNet.Tests.Classes.Connection
1614
{
@@ -82,23 +80,26 @@ protected override void Act()
8280
}
8381
}
8482

85-
[TestMethodForPlatform(nameof(OSPlatform.Windows))]
83+
[TestMethod]
84+
[OSCondition(OperatingSystems.Windows)]
8685
public void ConnectShouldHaveThrownSshOperationTimeoutExceptionOnWindows()
8786
{
8887
Assert.IsNull(_actualException.InnerException);
8988
Assert.IsInstanceOfType<SshOperationTimeoutException>(_actualException);
9089
Assert.AreEqual(string.Format(CultureInfo.InvariantCulture, "Connection failed to establish within {0} milliseconds.", _connectionInfo.Timeout.TotalMilliseconds), _actualException.Message);
9190
}
9291

93-
[TestMethodForPlatform(nameof(OSPlatform.Linux))]
92+
[TestMethod]
93+
[OSCondition(OperatingSystems.Linux)]
9494
public void ConnectShouldHaveThrownSshOperationTimeoutExceptionOnLinux()
9595
{
9696
Assert.IsNull(_actualException.InnerException);
9797
Assert.IsInstanceOfType<SocketException>(_actualException);
9898
Assert.AreEqual("Connection refused", _actualException.Message);
9999
}
100100

101-
[TestMethodForPlatform(nameof(OSPlatform.Windows))]
101+
[TestMethod]
102+
[OSCondition(OperatingSystems.Windows)]
102103
public void ConnectShouldHaveRespectedTimeoutOnWindows()
103104
{
104105
var errorText = string.Format("Elapsed: {0}, Timeout: {1}",

test/Renci.SshNet.Tests/Classes/Connection/Socks4ConnectorTest_Connect_TimeoutConnectingToProxy.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,12 @@
22
using System.Diagnostics;
33
using System.Globalization;
44
using System.Net.Sockets;
5-
using System.Runtime.InteropServices;
65

76
using Microsoft.VisualStudio.TestTools.UnitTesting;
87

98
using Moq;
109

1110
using Renci.SshNet.Common;
12-
using Renci.SshNet.Tests.Common;
1311

1412
namespace Renci.SshNet.Tests.Classes.Connection
1513
{
@@ -70,23 +68,26 @@ protected override void Act()
7068
}
7169
}
7270

73-
[TestMethodForPlatform(nameof(OSPlatform.Windows))]
71+
[TestMethod]
72+
[OSCondition(OperatingSystems.Windows)]
7473
public void ConnectShouldHaveThrownSshOperationTimeoutExceptionOnWindows()
7574
{
7675
Assert.IsNull(_actualException.InnerException);
7776
Assert.IsInstanceOfType<SshOperationTimeoutException>(_actualException);
7877
Assert.AreEqual(string.Format(CultureInfo.InvariantCulture, "Connection failed to establish within {0} milliseconds.", _connectionInfo.Timeout.TotalMilliseconds), _actualException.Message);
7978
}
8079

81-
[TestMethodForPlatform(nameof(OSPlatform.Linux))]
80+
[TestMethod]
81+
[OSCondition(OperatingSystems.Linux)]
8282
public void ConnectShouldHaveThrownSshOperationTimeoutExceptionOnLinux()
8383
{
8484
Assert.IsNull(_actualException.InnerException);
8585
Assert.IsInstanceOfType<SocketException>(_actualException);
8686
Assert.AreEqual("Connection refused", _actualException.Message);
8787
}
8888

89-
[TestMethodForPlatform(nameof(OSPlatform.Windows))]
89+
[TestMethod]
90+
[OSCondition(OperatingSystems.Windows)]
9091
public void ConnectShouldHaveRespectedTimeoutOnWindows()
9192
{
9293
var errorText = string.Format("Elapsed: {0}, Timeout: {1}",

test/Renci.SshNet.Tests/Classes/Connection/Socks5ConnectorTest_Connect_TimeoutConnectingToProxy.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,12 @@
22
using System.Diagnostics;
33
using System.Globalization;
44
using System.Net.Sockets;
5-
using System.Runtime.InteropServices;
65

76
using Microsoft.VisualStudio.TestTools.UnitTesting;
87

98
using Moq;
109

1110
using Renci.SshNet.Common;
12-
using Renci.SshNet.Tests.Common;
1311

1412
namespace Renci.SshNet.Tests.Classes.Connection
1513
{
@@ -71,23 +69,26 @@ protected override void Act()
7169
}
7270
}
7371

74-
[TestMethodForPlatform(nameof(OSPlatform.Windows))]
72+
[TestMethod]
73+
[OSCondition(OperatingSystems.Windows)]
7574
public void ConnectShouldHaveThrownSshOperationTimeoutExceptionOnWindows()
7675
{
7776
Assert.IsNull(_actualException.InnerException);
7877
Assert.IsInstanceOfType<SshOperationTimeoutException>(_actualException);
7978
Assert.AreEqual(string.Format(CultureInfo.InvariantCulture, "Connection failed to establish within {0} milliseconds.", _connectionInfo.Timeout.TotalMilliseconds), _actualException.Message);
8079
}
8180

82-
[TestMethodForPlatform(nameof(OSPlatform.Linux))]
81+
[TestMethod]
82+
[OSCondition(OperatingSystems.Linux)]
8383
public void ConnectShouldHaveThrownSshOperationTimeoutExceptionOnLinux()
8484
{
8585
Assert.IsNull(_actualException.InnerException);
8686
Assert.IsInstanceOfType<SocketException>(_actualException);
8787
Assert.AreEqual("Connection refused", _actualException.Message);
8888
}
8989

90-
[TestMethodForPlatform(nameof(OSPlatform.Windows))]
90+
[TestMethod]
91+
[OSCondition(OperatingSystems.Windows)]
9192
public void ConnectShouldHaveRespectedTimeoutOnWindows()
9293
{
9394
var errorText = string.Format("Elapsed: {0}, Timeout: {1}",

test/Renci.SshNet.Tests/Classes/ForwardedPortDynamicTest_Dispose_PortStarted_ChannelNotBound.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
using System.Collections.Generic;
33
using System.Net;
44
using System.Net.Sockets;
5-
using System.Runtime.InteropServices;
65
using System.Threading;
76

87
using Microsoft.Extensions.Logging.Abstractions;
@@ -12,7 +11,6 @@
1211

1312
using Renci.SshNet.Channels;
1413
using Renci.SshNet.Common;
15-
using Renci.SshNet.Tests.Common;
1614

1715
namespace Renci.SshNet.Tests.Classes
1816
{
@@ -108,7 +106,8 @@ public void ForwardedPortShouldRefuseNewConnections()
108106
}
109107

110108
// TODO We should investigate why this method doesn't work on Linux
111-
[TestMethodForPlatform(nameof(OSPlatform.Windows))]
109+
[TestMethod]
110+
[OSCondition(OperatingSystems.Windows)]
112111
public void ExistingConnectionShouldBeClosed()
113112
{
114113
try

test/Renci.SshNet.Tests/Classes/ForwardedPortDynamicTest_Stop_PortStarted_ChannelNotBound.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
using System.Collections.Generic;
33
using System.Net;
44
using System.Net.Sockets;
5-
using System.Runtime.InteropServices;
65
using System.Threading;
76

87
using Microsoft.Extensions.Logging.Abstractions;
@@ -12,7 +11,6 @@
1211

1312
using Renci.SshNet.Channels;
1413
using Renci.SshNet.Common;
15-
using Renci.SshNet.Tests.Common;
1614

1715
namespace Renci.SshNet.Tests.Classes
1816
{
@@ -112,7 +110,8 @@ public void ForwardedPortShouldRefuseNewConnections()
112110
}
113111

114112
// TODO We should investigate why this method doesn't work on Linux
115-
[TestMethodForPlatform(nameof(OSPlatform.Windows))]
113+
[TestMethod]
114+
[OSCondition(OperatingSystems.Windows)]
116115
public void ExistingConnectionShouldBeClosed()
117116
{
118117
try

test/Renci.SshNet.Tests/Common/TestMethodForPlatformAttribute.cs

Lines changed: 0 additions & 39 deletions
This file was deleted.

0 commit comments

Comments
 (0)