Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add validity checks for HTTP datagrams #85

Merged
merged 8 commits into from Jan 27, 2017
81 changes: 81 additions & 0 deletions PcapDotNet/src/PcapDotNet.Packets.Test/HttpTests.cs
Expand Up @@ -108,6 +108,7 @@ public void RandomHttpTest()
if (httpLayer.Header != null)
{
Assert.AreEqual(httpLayer.Header.GetHashCode(), httpDatagram.Header.GetHashCode());
Assert.IsTrue(httpDatagram.IsValidStart, "IsValidStart");

foreach (var field in httpLayer.Header)
Assert.IsFalse(field.Equals("abc"));
Expand Down Expand Up @@ -470,6 +471,86 @@ public void HttpRequestMethodBadKnownTest()
Assert.IsNotNull(new HttpRequestMethod(HttpRequestKnownMethod.Unknown));
}

[TestMethod]
public void HttpIsValidStartRequestValidTest()
{
var packet = BuildPacket("UnknownMethod / HTTP/1.0\r\n\r\n");

Assert.IsTrue(packet.Ethernet.IpV4.Tcp.Http.IsValidStart);
}

[TestMethod]
public void HttpIsValidStartRequestWithMissingUriNotAllowedTest()
{
var packet = BuildPacket("GET HTTP/1.1\r\n\r\n");

Assert.IsFalse(packet.Ethernet.IpV4.Tcp.Http.IsValidStart);
}

[TestMethod]
public void HttpIsValidStartRequestWithMissingVersionNumberNotAllowedTest()
{
var packet = BuildPacket("GET / HTTP/\r\n\r\n");

Assert.IsFalse(packet.Ethernet.IpV4.Tcp.Http.IsValidStart);
}

[TestMethod]
public void HttpIsValidStartRequestWithMissingVersionNotAllowedTest()
{
var packet = BuildPacket("GET /\r\n\r\n");

Assert.IsFalse(packet.Ethernet.IpV4.Tcp.Http.IsValidStart);
}

[TestMethod]
public void HttpIsValidStartRequestWithMissingMethodNotAllowedTest()
{
var packet = BuildPacket(" / HTTP/1.0\r\n\r\n");

Assert.IsFalse(packet.Ethernet.IpV4.Tcp.Http.IsValidStart);
}

[TestMethod]
public void HttpIsValidStartResponseValidTest()
{
var packet = BuildPacket("HTTP/1.0 200 OK\r\n\r\n");

Assert.IsTrue(packet.Ethernet.IpV4.Tcp.Http.IsValidStart);
}

[TestMethod]
public void HttpIsValidStartResponseMinimalValidTest()
{
var packet = BuildPacket("HTTP/1.0 200 \r\n\r\n");

Assert.IsTrue(packet.Ethernet.IpV4.Tcp.Http.IsValidStart);
}

[TestMethod]
public void HttpIsValidStartResponseWithMissingVersionNumberNotAllowedTest()
{
var packet = BuildPacket("HTTP/ 200 OK\r\n\r\n");

Assert.IsFalse(packet.Ethernet.IpV4.Tcp.Http.IsValidStart);
}

[TestMethod]
public void HttpIsValidStartResponseWithMissingVersionNotAllowed()
{
var packet = BuildPacket(" 200 OK\r\n\r\n");

Assert.IsFalse(packet.Ethernet.IpV4.Tcp.Http.IsValidStart);
}

[TestMethod]
public void HttpIsValidStartResponseWithMissingStatusCodeNotAllowedTest()
{
var packet = BuildPacket("HTTP/1.0 OK \r\n\r\n");

Assert.IsFalse(packet.Ethernet.IpV4.Tcp.Http.IsValidStart);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you only care about IsValidStart in these tests, you could put "IsValidStart" as part of the test names.
Otherwise you could test other properties for these use cases.


private static void TestHttpRequest(string httpString, string expectedMethodString = null, string expectedUri = null, HttpVersion expectedVersion = null, HttpHeader expectedHeader = null, string expectedBodyString = null)
Copy link
Contributor

@bricknerb bricknerb Jan 21, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test the new method also in RandomHttpTest

{
Datagram expectedBody = expectedBodyString == null ? null : new Datagram(Encoding.ASCII.GetBytes(expectedBodyString));
Expand Down
20 changes: 20 additions & 0 deletions PcapDotNet/src/PcapDotNet.Packets/Http/HttpDatagram.cs
Expand Up @@ -239,6 +239,24 @@ internal class ParseInfoBase
/// </summary>
public Datagram Body { get; private set; }

/// <summary>
/// True if this datagram contains a valid start for an HTTP message.
/// </summary>
public bool IsValidStart
{
get
{
if (_isValidStart == null)
_isValidStart = CalculateIsValidStart();
return _isValidStart.Value;
}
}

/// <summary>
/// Calculate whether the HTTP datagram has a valid start.
/// </summary>
protected abstract bool CalculateIsValidStart();

internal static HttpDatagram CreateDatagram(byte[] buffer, int offset, int length)
{
if (length >= _httpSlash.Length && buffer.SequenceEqual(offset, _httpSlash, 0, _httpSlash.Length))
Expand Down Expand Up @@ -355,5 +373,7 @@ private static Datagram ParseChunkedBody(byte[] buffer, int offset, int length)
}

private static readonly byte[] _httpSlash = Encoding.ASCII.GetBytes("HTTP/");

private bool? _isValidStart;
}
}
8 changes: 8 additions & 0 deletions PcapDotNet/src/PcapDotNet.Packets/Http/HttpRequestDatagram.cs
Expand Up @@ -47,6 +47,14 @@ public override ILayer ExtractLayer()
};
}

/// <summary>
/// An HTTP Request has a valid start if it contains a method, an URI, and a version.
/// </summary>
protected override bool CalculateIsValidStart()
{
return Method != null && !string.IsNullOrEmpty(Uri) && Version != null;
}

internal HttpRequestDatagram(byte[] buffer, int offset, int length)
: this(buffer, offset, Parse(buffer, offset, length))
{
Expand Down
Expand Up @@ -50,6 +50,14 @@ public override ILayer ExtractLayer()
};
}

/// <summary>
/// An HTTP response has a valid start if it contains a version and a status code.
/// </summary>
protected override bool CalculateIsValidStart()
{
return Version != null && StatusCode != null;
}

internal HttpResponseDatagram(byte[] buffer, int offset, int length)
: this(buffer, offset, Parse(buffer, offset, length))
{
Expand Down