Skip to content

Commit

Permalink
Fix frame boundary detection in SslStream (#104606)
Browse files Browse the repository at this point in the history
  • Loading branch information
rzikm committed Jul 11, 2024
1 parent 8ba8249 commit 0d426df
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,7 @@ private ProtocolToken ProcessTlsFrame(int frameSize)
{
TlsFrameHeader nextHeader = default;

if (!TlsFrameHelper.TryGetFrameHeader(_buffer.EncryptedReadOnlySpan.Slice(chunkSize), ref nextHeader))
if (!TlsFrameHelper.TryGetFrameHeader(availableData.Slice(chunkSize), ref nextHeader))
{
break;
}
Expand All @@ -478,7 +478,7 @@ private ProtocolToken ProcessTlsFrame(int frameSize)

// Can process more handshake frames in single step or during TLS1.3 post-handshake auth, but we should
// avoid processing too much so as to preserve API boundary between handshake and I/O.
if ((nextHeader.Type != TlsContentType.Handshake && nextHeader.Type != TlsContentType.ChangeCipherSpec) && !_isRenego || frameSize > _buffer.EncryptedLength)
if ((nextHeader.Type != TlsContentType.Handshake && nextHeader.Type != TlsContentType.ChangeCipherSpec) && !_isRenego || frameSize > availableData.Length - chunkSize)
{
// We don't have full frame left or we already have app data which needs to be processed by decrypt.
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,10 @@ public enum FramingType
// 1 byte reads
ByteByByte,

// coalesce reads to biggest chunks possible
// Receive data at chunks, not necessarily respecting frame boundaries
Chunked,

// Coalesce reads to biggest chunks possible
Coalescing
}

Expand Down Expand Up @@ -129,7 +132,6 @@ public async Task Handshake_Success(FramingType framingType, SslProtocols sslPro
Assert.True(serverStream.ReadCalled, "Mocked read method was not used");

await TestHelper.PingPong(client, server);

}

internal class ConfigurableReadStream : Stream
Expand Down Expand Up @@ -168,6 +170,7 @@ public override async ValueTask<int> ReadAsync(Memory<byte> buffer, Cancellation
{
case FramingType.ByteByByte:
return await _stream.ReadAsync(buffer.Length > 0 ? buffer.Slice(0, 1) : buffer, cancellationToken);

case FramingType.Coalescing:
{
if (buffer.Length > 0)
Expand All @@ -178,6 +181,24 @@ public override async ValueTask<int> ReadAsync(Memory<byte> buffer, Cancellation
}
return await _stream.ReadAsync(buffer, cancellationToken);
}
case FramingType.Chunked:
{
if (buffer.Length > 0)
{
// wait 10ms, this should be enough for the other side to write as much data
// as it will ever write before receiving something back.
await Task.Delay(10);

const int maxRead = 1519; // arbitrarily chosen chunk size

if (buffer.Length > maxRead)
{
buffer = buffer.Slice(0, maxRead);
}
}
return await _stream.ReadAsync(buffer, cancellationToken);
}

default:
throw new NotImplementedException();
}
Expand Down

0 comments on commit 0d426df

Please sign in to comment.