Skip to content

Commit c141c7d

Browse files
committed
Ignore data of SSH_MSG_IGNORE when its specified length is greater than the actual available bytes.
Fixes issue #41.
1 parent 76a92cf commit c141c7d

File tree

3 files changed

+267
-5
lines changed

3 files changed

+267
-5
lines changed

src/Renci.SshNet.Tests/Classes/Common/SshDataTest.cs

+208-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using Microsoft.VisualStudio.TestTools.UnitTesting;
1+
using System;
2+
using Microsoft.VisualStudio.TestTools.UnitTesting;
23
using Renci.SshNet.Common;
34

45
namespace Renci.SshNet.Tests.Classes.Common
@@ -10,7 +11,7 @@ public class SshDataTest
1011
public void Write_Boolean_False()
1112
{
1213
var sshData = new BoolSshData(false);
13-
14+
1415
var bytes = sshData.GetBytes();
1516

1617
Assert.AreEqual((byte) 0, bytes[0]);
@@ -26,6 +27,125 @@ public void Write_Boolean_True()
2627
Assert.AreEqual((byte) 1, bytes[0]);
2728
}
2829

30+
[TestMethod]
31+
public void Load_Data()
32+
{
33+
const uint one = 123456u;
34+
const uint two = 456789u;
35+
36+
var sshDataStream = new SshDataStream(8);
37+
sshDataStream.Write(one);
38+
sshDataStream.Write(two);
39+
40+
var sshData = sshDataStream.ToArray();
41+
42+
var request = new RequestSshData();
43+
request.Load(sshData);
44+
45+
Assert.AreEqual(one, request.ValueOne);
46+
Assert.AreEqual(two, request.ValueTwo);
47+
}
48+
49+
[TestMethod]
50+
public void Load_Data_ShouldThrowArgumentNullExceptionWhenDataIsNull()
51+
{
52+
const byte[] sshData = null;
53+
var request = new RequestSshData();
54+
55+
try
56+
{
57+
request.Load(sshData);
58+
Assert.Fail();
59+
}
60+
catch (ArgumentNullException ex)
61+
{
62+
Assert.IsNull(ex.InnerException);
63+
Assert.AreEqual("data", ex.ParamName);
64+
}
65+
}
66+
67+
[TestMethod]
68+
public void Load_DataAndOffsetAndCount()
69+
{
70+
const uint one = 123456u;
71+
const uint two = 456789u;
72+
73+
var sshDataStream = new SshDataStream(11);
74+
sshDataStream.WriteByte(0x05);
75+
sshDataStream.WriteByte(0x07);
76+
sshDataStream.WriteByte(0x0f);
77+
sshDataStream.Write(one);
78+
sshDataStream.Write(two);
79+
80+
var sshData = sshDataStream.ToArray();
81+
82+
var request = new RequestSshData();
83+
request.Load(sshData, 3, sshData.Length - 3);
84+
85+
Assert.AreEqual(one, request.ValueOne);
86+
Assert.AreEqual(two, request.ValueTwo);
87+
}
88+
89+
90+
[TestMethod]
91+
public void OfType()
92+
{
93+
const uint one = 123456u;
94+
const uint two = 456789u;
95+
96+
var sshDataStream = new SshDataStream(8);
97+
sshDataStream.Write(one);
98+
sshDataStream.Write(two);
99+
100+
var sshData = sshDataStream.ToArray();
101+
102+
var request = new RequestSshData();
103+
request.Load(sshData);
104+
105+
var reply = request.OfType<ReplySshData>();
106+
Assert.IsNotNull(reply);
107+
Assert.AreEqual(one, reply.ValueOne);
108+
}
109+
110+
[TestMethod]
111+
public void OfType_LoadWithOffset()
112+
{
113+
const uint one = 123456u;
114+
const uint two = 456789u;
115+
116+
var sshDataStream = new SshDataStream(11);
117+
sshDataStream.WriteByte(0x05);
118+
sshDataStream.WriteByte(0x07);
119+
sshDataStream.WriteByte(0x0f);
120+
sshDataStream.Write(one);
121+
sshDataStream.Write(two);
122+
123+
var sshData = sshDataStream.ToArray();
124+
125+
var request = new RequestSshData();
126+
request.Load(sshData, 3, sshData.Length - 3);
127+
var reply = request.OfType<ReplySshData>();
128+
Assert.IsNotNull(reply);
129+
Assert.AreEqual(one, reply.ValueOne);
130+
}
131+
132+
[TestMethod]
133+
public void OfType_ShouldThrowArgumentNullExceptionWhenNoDataIsLoaded()
134+
{
135+
var request = new RequestSshData();
136+
137+
try
138+
{
139+
request.OfType<ReplySshData>();
140+
Assert.Fail();
141+
}
142+
catch (ArgumentNullException ex)
143+
{
144+
Assert.IsNull(ex.InnerException);
145+
Assert.AreEqual("data", ex.ParamName);
146+
}
147+
}
148+
29149
private class BoolSshData : SshData
30150
{
31151
private readonly bool _value;
@@ -54,5 +174,91 @@ protected override void SaveData()
54174
Write(_value);
55175
}
56176
}
177+
178+
private class RequestSshData : SshData
179+
{
180+
private uint _valueOne;
181+
private uint _valueTwo;
182+
183+
public RequestSshData()
184+
{
185+
}
186+
187+
public RequestSshData(uint one, uint two)
188+
{
189+
_valueOne = one;
190+
_valueTwo = two;
191+
}
192+
193+
protected override int BufferCapacity
194+
{
195+
get
196+
{
197+
var capacity = base.BufferCapacity;
198+
capacity += 4; // ValueOne
199+
capacity += 4; // ValueTwo
200+
return capacity;
201+
}
202+
}
203+
204+
public uint ValueOne
205+
{
206+
get { return _valueOne; }
207+
set { _valueOne = value; }
208+
}
209+
210+
public uint ValueTwo
211+
{
212+
get { return _valueTwo; }
213+
set { _valueTwo = value; }
214+
}
215+
216+
protected override void LoadData()
217+
{
218+
_valueOne = ReadUInt32();
219+
_valueTwo = ReadUInt32();
220+
}
221+
222+
protected override void SaveData()
223+
{
224+
Write(ValueOne);
225+
Write(ValueTwo);
226+
}
227+
}
228+
229+
private class ReplySshData : SshData
230+
{
231+
private uint _valueOne;
232+
233+
public ReplySshData()
234+
{
235+
}
236+
237+
protected override int BufferCapacity
238+
{
239+
get
240+
{
241+
var capacity = base.BufferCapacity;
242+
capacity += 4; // ValueOne
243+
return capacity;
244+
}
245+
}
246+
247+
public uint ValueOne
248+
{
249+
get { return _valueOne; }
250+
set { _valueOne = value; }
251+
}
252+
253+
protected override void LoadData()
254+
{
255+
_valueOne = ReadUInt32();
256+
}
257+
258+
protected override void SaveData()
259+
{
260+
Write(ValueOne);
261+
}
262+
}
57263
}
58264
}

src/Renci.SshNet.Tests/Classes/Messages/Transport/IgnoreMessageTest.cs

+42-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Globalization;
23
using System.Linq;
34
using Renci.SshNet.Common;
45
using Renci.SshNet.Messages.Transport;
@@ -38,7 +39,7 @@ public void Constructor_Data()
3839
[TestMethod]
3940
public void Constructor_Data_ShouldThrowArgumentNullExceptionWhenDataIsNull()
4041
{
41-
byte[] data = null;
42+
const byte[] data = null;
4243

4344
try
4445
{
@@ -85,11 +86,50 @@ public void Load()
8586
var bytes = ignoreMessage.GetBytes();
8687
var target = new IgnoreMessage();
8788

88-
target.Load(bytes);
89+
target.Load(bytes, 1, bytes.Length - 1);
8990

9091
Assert.IsNotNull(target.Data);
9192
Assert.AreEqual(_data.Length, target.Data.Length);
9293
Assert.IsTrue(target.Data.SequenceEqual(_data));
9394
}
95+
96+
[TestMethod]
97+
public void Load_ShouldIgnoreDataWhenItsLengthIsGreatherThanItsActualBytes()
98+
{
99+
var ssh = new SshDataStream(1);
100+
ssh.WriteByte(2); // Type
101+
ssh.Write(5u); // Data length
102+
ssh.Write(new byte[3]); // Data
103+
104+
var ignoreMessageBytes = ssh.ToArray();
105+
106+
var ignoreMessage = new IgnoreMessage();
107+
ignoreMessage.Load(ignoreMessageBytes, 1, ignoreMessageBytes.Length - 1);
108+
Assert.IsNotNull(ignoreMessage.Data);
109+
Assert.AreEqual(0, ignoreMessage.Data.Length);
110+
}
111+
112+
[TestMethod]
113+
public void Load_ShouldThrowNotSupportedExceptionWhenDataLengthIsGreaterThanInt32MaxValue()
114+
{
115+
var ssh = new SshDataStream(1);
116+
ssh.WriteByte(2); // Type
117+
ssh.Write(uint.MaxValue); // Data length
118+
ssh.Write(new byte[3]);
119+
120+
var ignoreMessageBytes = ssh.ToArray();
121+
var ignoreMessage = new IgnoreMessage();
122+
123+
try
124+
{
125+
ignoreMessage.Load(ignoreMessageBytes, 1, ignoreMessageBytes.Length - 1);
126+
Assert.Fail();
127+
}
128+
catch (NotSupportedException ex)
129+
{
130+
Assert.IsNull(ex.InnerException);
131+
Assert.AreEqual(string.Format(CultureInfo.CurrentCulture, "Data longer than {0} is not supported.", int.MaxValue), ex.Message);
132+
}
133+
}
94134
}
95135
}

src/Renci.SshNet/Messages/Transport/IgnoreMessage.cs

+17-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
using System;
2+
using System.Globalization;
3+
using Renci.SshNet.Abstractions;
24
using Renci.SshNet.Common;
35

46
namespace Renci.SshNet.Messages.Transport
@@ -58,7 +60,21 @@ public IgnoreMessage(byte[] data)
5860
/// </summary>
5961
protected override void LoadData()
6062
{
61-
Data = ReadBinary();
63+
var dataLength = ReadUInt32();
64+
if (dataLength > int.MaxValue)
65+
{
66+
throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Data longer than {0} is not supported.", int.MaxValue));
67+
}
68+
69+
if (dataLength > (DataStream.Length - DataStream.Position))
70+
{
71+
DiagnosticAbstraction.Log("SSH_MSG_IGNORE: Length exceeds data bytes, data ignored.");
72+
Data = Array<byte>.Empty;
73+
}
74+
else
75+
{
76+
Data = ReadBytes((int) dataLength);
77+
}
6278
}
6379

6480
/// <summary>

0 commit comments

Comments
 (0)