Skip to content

Commit a710517

Browse files
committed
remember record length
1 parent 507f62e commit a710517

File tree

1 file changed

+12
-3
lines changed

1 file changed

+12
-3
lines changed

src/Servers/Kestrel/Core/src/Middleware/TlsListener.cs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ internal async Task OnTlsClientHelloAsync(ConnectionContext connection, Cancella
2323
{
2424
var input = connection.Transport.Input;
2525
ClientHelloParseState parseState = ClientHelloParseState.NotEnoughData;
26+
short recordLength = -1; // remembers the length of TLS record to not re-parse header on every iteration
2627

2728
while (true)
2829
{
@@ -38,7 +39,7 @@ internal async Task OnTlsClientHelloAsync(ConnectionContext connection, Cancella
3839
break;
3940
}
4041

41-
parseState = TryParseClientHello(buffer, out var clientHelloBytes);
42+
parseState = TryParseClientHello(buffer, ref recordLength, out var clientHelloBytes);
4243
if (parseState == ClientHelloParseState.NotEnoughData)
4344
{
4445
// if no data will be added, and we still lack enough bytes
@@ -81,10 +82,18 @@ internal async Task OnTlsClientHelloAsync(ConnectionContext connection, Cancella
8182
/// TLS 1.2: https://datatracker.ietf.org/doc/html/rfc5246#section-6.2
8283
/// TLS 1.3: https://datatracker.ietf.org/doc/html/rfc8446#section-5.1
8384
/// </summary>
84-
private static ClientHelloParseState TryParseClientHello(ReadOnlySequence<byte> buffer, out ReadOnlySequence<byte> clientHelloBytes)
85+
private static ClientHelloParseState TryParseClientHello(ReadOnlySequence<byte> buffer, ref short recordLength, out ReadOnlySequence<byte> clientHelloBytes)
8586
{
8687
clientHelloBytes = default;
8788

89+
// in case bad actor will be sending a TLS client hello one byte at a time
90+
// and we know the expected length of TLS client hello,
91+
// we can check and fail fastly here instead of re-parsing the TLS client hello "header" on each iteration
92+
if (recordLength != -1 && buffer.Length < 5 + recordLength)
93+
{
94+
return ClientHelloParseState.NotEnoughData;
95+
}
96+
8897
if (buffer.Length < 6)
8998
{
9099
return ClientHelloParseState.NotEnoughData;
@@ -105,7 +114,7 @@ private static ClientHelloParseState TryParseClientHello(ReadOnlySequence<byte>
105114
}
106115

107116
// Record length
108-
if (!reader.TryReadBigEndian(out short recordLength))
117+
if (!reader.TryReadBigEndian(out recordLength))
109118
{
110119
return ClientHelloParseState.NotTlsClientHello;
111120
}

0 commit comments

Comments
 (0)