From f444f5a284850634ad35e8ae9b104f504bc331f9 Mon Sep 17 00:00:00 2001 From: Matthew Endsley Date: Wed, 31 Mar 2021 12:16:11 -0700 Subject: [PATCH] Add unit test to confirm malformed GCM record bug --- Hazel.UnitTests/Dtls/ConnectionTests.cs | 78 +++++++++++++++++++ .../ThreadLimitedUdpServerConnection.cs | 2 +- 2 files changed, 79 insertions(+), 1 deletion(-) diff --git a/Hazel.UnitTests/Dtls/ConnectionTests.cs b/Hazel.UnitTests/Dtls/ConnectionTests.cs index 0a8077e..3279ce2 100644 --- a/Hazel.UnitTests/Dtls/ConnectionTests.cs +++ b/Hazel.UnitTests/Dtls/ConnectionTests.cs @@ -2,6 +2,7 @@ using Hazel.Dtls; using Hazel.Udp; using Hazel.Udp.FewerThreads; using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; using System.Net; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; @@ -148,5 +149,82 @@ IsdbLCwHYD3GVgk/D7NVxyU= Assert.IsFalse(serverDisconnected); } } + + class MalformedDTLSListener : DtlsConnectionListener + { + public MalformedDTLSListener(int numWorkers, IPEndPoint endPoint, ILogger logger, IPMode ipMode = IPMode.IPv4) + : base(numWorkers, endPoint, logger, ipMode) + { + } + + public void InjectPacket(ByteSpan packet, IPEndPoint peerAddress, ConnectionId connectionId) + { + MessageReader reader = MessageReader.GetSized(packet.Length); + reader.Length = packet.Length; + Array.Copy(packet.GetUnderlyingArray(), packet.Offset, reader.Buffer, reader.Offset, packet.Length); + + this.ProcessIncomingMessageFromOtherThread(reader, peerAddress, connectionId); + } + + protected override void ProcessIncomingMessageFromOtherThread(MessageReader reader, IPEndPoint peerAddress, ConnectionId connectionId) + { + base.ProcessIncomingMessageFromOtherThread(reader, peerAddress, connectionId); + } + } + + [TestMethod] + public void TestMalformedApplicationData() + { + IPEndPoint ep = new IPEndPoint(IPAddress.Loopback, 27510); + + IPEndPoint connectionEndPoint = ep; + DtlsConnectionListener.ConnectionId connectionId = new ThreadLimitedUdpConnectionListener.ConnectionId(); + + Semaphore signal = new Semaphore(0, int.MaxValue); + + using (MalformedDTLSListener listener = new MalformedDTLSListener(2, new IPEndPoint(IPAddress.Any, ep.Port), new TestLogger())) + using (DtlsUnityConnection connection = new DtlsUnityConnection(new TestLogger(), ep)) + { + listener.SetCertificate(GetCertificateForServer()); + connection.SetValidServerCertificates(GetCertificateForClient()); + + listener.NewConnection += (evt) => + { + connectionEndPoint = evt.Connection.EndPoint; + connectionId = ((ThreadLimitedUdpServerConnection)evt.Connection).ConnectionId; + + signal.Release(); + evt.Connection.Disconnected += (o, et) => { + }; + }; + connection.Disconnected += (o, evt) => { + signal.Release(); + }; + + listener.Start(); + connection.Connect(); + + // wait for the client to connect + signal.WaitOne(10); + + ByteSpan data = new byte[5] { 0x01, 0x02, 0x03, 0x04, 0x05 }; + + Record record = new Record(); + record.ContentType = ContentType.ApplicationData; + record.Epoch = 1; + record.SequenceNumber = 10; + record.Length = (ushort)data.Length; + + ByteSpan encoded = new byte[Record.Size + data.Length]; + record.Encode(encoded); + data.CopyTo(encoded.Slice(Record.Size)); + + listener.InjectPacket(encoded, connectionEndPoint, connectionId); + + // wait for the client to disconnect + listener.Dispose(); + signal.WaitOne(100); + } + } } } diff --git a/Hazel/FewerThreads/ThreadLimitedUdpServerConnection.cs b/Hazel/FewerThreads/ThreadLimitedUdpServerConnection.cs index 0cb864f..2f57794 100644 --- a/Hazel/FewerThreads/ThreadLimitedUdpServerConnection.cs +++ b/Hazel/FewerThreads/ThreadLimitedUdpServerConnection.cs @@ -20,7 +20,7 @@ namespace Hazel.Udp.FewerThreads /// public ThreadLimitedUdpConnectionListener Listener { get; private set; } - private ThreadLimitedUdpConnectionListener.ConnectionId ConnectionId; + public ThreadLimitedUdpConnectionListener.ConnectionId ConnectionId { get; private set; } /// /// Creates a UdpConnection for the virtual connection to the endpoint. -- 2.39.5