Enforce max frame size #2651
This commit is contained in:
parent
810a302e66
commit
a217206f1f
|
|
@ -497,9 +497,6 @@ For more information on configuring HTTPS see https://go.microsoft.com/fwlink/?l
|
||||||
<data name="MultipleCertificateSources" xml:space="preserve">
|
<data name="MultipleCertificateSources" xml:space="preserve">
|
||||||
<value>The endpoint {endpointName} specified multiple certificate sources.</value>
|
<value>The endpoint {endpointName} specified multiple certificate sources.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Http2NotSupported" xml:space="preserve">
|
|
||||||
<value>HTTP/2 support is experimental, see https://go.microsoft.com/fwlink/?linkid=866785 to enable it.</value>
|
|
||||||
</data>
|
|
||||||
<data name="WritingToResponseBodyAfterResponseCompleted" xml:space="preserve">
|
<data name="WritingToResponseBodyAfterResponseCompleted" xml:space="preserve">
|
||||||
<value>Cannot write to the response body, the response has completed.</value>
|
<value>Cannot write to the response body, the response has completed.</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -518,4 +515,7 @@ For more information on configuring HTTPS see https://go.microsoft.com/fwlink/?l
|
||||||
<data name="ConnectionTimedOutByServer" xml:space="preserve">
|
<data name="ConnectionTimedOutByServer" xml:space="preserve">
|
||||||
<value>The connection was timed out by the server.</value>
|
<value>The connection was timed out by the server.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Http2ErrorFrameOverLimit" xml:space="preserve">
|
||||||
|
<value>The received frame size of {size} exceeds the limit {limit}.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
@ -157,7 +157,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
|
||||||
{
|
{
|
||||||
if (!readableBuffer.IsEmpty)
|
if (!readableBuffer.IsEmpty)
|
||||||
{
|
{
|
||||||
if (Http2FrameReader.ReadFrame(readableBuffer, _incomingFrame, out consumed, out examined))
|
if (Http2FrameReader.ReadFrame(readableBuffer, _incomingFrame, _serverSettings.MaxFrameSize, out consumed, out examined))
|
||||||
{
|
{
|
||||||
Log.LogTrace($"Connection id {ConnectionId} received {_incomingFrame.Type} frame with flags 0x{_incomingFrame.Flags:x} and length {_incomingFrame.Length} for stream ID {_incomingFrame.StreamId}");
|
Log.LogTrace($"Connection id {ConnectionId} received {_incomingFrame.Type} frame with flags 0x{_incomingFrame.Flags:x} and length {_incomingFrame.Length} for stream ID {_incomingFrame.StreamId}");
|
||||||
await ProcessFrameAsync<TContext>(application);
|
await ProcessFrameAsync<TContext>(application);
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
|
||||||
{
|
{
|
||||||
public static class Http2FrameReader
|
public static class Http2FrameReader
|
||||||
{
|
{
|
||||||
public static bool ReadFrame(ReadOnlySequence<byte> readableBuffer, Http2Frame frame, out SequencePosition consumed, out SequencePosition examined)
|
public static bool ReadFrame(ReadOnlySequence<byte> readableBuffer, Http2Frame frame, uint maxFrameSize, out SequencePosition consumed, out SequencePosition examined)
|
||||||
{
|
{
|
||||||
consumed = readableBuffer.Start;
|
consumed = readableBuffer.Start;
|
||||||
examined = readableBuffer.End;
|
examined = readableBuffer.End;
|
||||||
|
|
@ -22,6 +22,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
|
||||||
var headerSlice = readableBuffer.Slice(0, Http2Frame.HeaderLength);
|
var headerSlice = readableBuffer.Slice(0, Http2Frame.HeaderLength);
|
||||||
headerSlice.CopyTo(frame.Raw);
|
headerSlice.CopyTo(frame.Raw);
|
||||||
|
|
||||||
|
if (frame.Length > maxFrameSize)
|
||||||
|
{
|
||||||
|
throw new Http2ConnectionErrorException(CoreStrings.FormatHttp2ErrorFrameOverLimit(frame.Length, maxFrameSize), Http2ErrorCode.FRAME_SIZE_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
if (readableBuffer.Length < Http2Frame.HeaderLength + frame.Length)
|
if (readableBuffer.Length < Http2Frame.HeaderLength + frame.Length)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -1778,20 +1778,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core
|
||||||
internal static string FormatMultipleCertificateSources(object endpointName)
|
internal static string FormatMultipleCertificateSources(object endpointName)
|
||||||
=> string.Format(CultureInfo.CurrentCulture, GetString("MultipleCertificateSources", "endpointName"), endpointName);
|
=> string.Format(CultureInfo.CurrentCulture, GetString("MultipleCertificateSources", "endpointName"), endpointName);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// HTTP/2 support is experimental, see https://go.microsoft.com/fwlink/?linkid=866785 to enable it.
|
|
||||||
/// </summary>
|
|
||||||
internal static string Http2NotSupported
|
|
||||||
{
|
|
||||||
get => GetString("Http2NotSupported");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// HTTP/2 support is experimental, see https://go.microsoft.com/fwlink/?linkid=866785 to enable it.
|
|
||||||
/// </summary>
|
|
||||||
internal static string FormatHttp2NotSupported()
|
|
||||||
=> GetString("Http2NotSupported");
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Cannot write to the response body, the response has completed.
|
/// Cannot write to the response body, the response has completed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -1876,6 +1862,20 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core
|
||||||
internal static string FormatConnectionTimedOutByServer()
|
internal static string FormatConnectionTimedOutByServer()
|
||||||
=> GetString("ConnectionTimedOutByServer");
|
=> GetString("ConnectionTimedOutByServer");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The received frame size of {size} exceeds the limit {limit}.
|
||||||
|
/// </summary>
|
||||||
|
internal static string Http2ErrorFrameOverLimit
|
||||||
|
{
|
||||||
|
get => GetString("Http2ErrorFrameOverLimit");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The received frame size of {size} exceeds the limit {limit}.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatHttp2ErrorFrameOverLimit(object size, object limit)
|
||||||
|
=> string.Format(CultureInfo.CurrentCulture, GetString("Http2ErrorFrameOverLimit", "size", "limit"), size, limit);
|
||||||
|
|
||||||
private static string GetString(string name, params string[] formatterNames)
|
private static string GetString(string name, params string[] formatterNames)
|
||||||
{
|
{
|
||||||
var value = _resourceManager.GetString(name);
|
var value = _resourceManager.GetString(name);
|
||||||
|
|
|
||||||
|
|
@ -299,6 +299,28 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
_decodedHeaders[name.GetAsciiStringNonNullCharacters()] = value.GetAsciiStringNonNullCharacters();
|
_decodedHeaders[name.GetAsciiStringNonNullCharacters()] = value.GetAsciiStringNonNullCharacters();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Frame_Received_OverMaxSize_FrameError()
|
||||||
|
{
|
||||||
|
await InitializeConnectionAsync(_echoApplication);
|
||||||
|
|
||||||
|
await StartStreamAsync(1, _browserRequestHeaders, endStream: false);
|
||||||
|
// Manually craft a frame where the size is too large. Our own frame class won't allow this.
|
||||||
|
// See Http2Frame.Length
|
||||||
|
var length = Http2Frame.MinAllowedMaxFrameSize + 1; // Too big
|
||||||
|
var frame = new byte[9 + length];
|
||||||
|
frame[0] = (byte)((length & 0x00ff0000) >> 16);
|
||||||
|
frame[1] = (byte)((length & 0x0000ff00) >> 8);
|
||||||
|
frame[2] = (byte)(length & 0x000000ff);
|
||||||
|
await SendAsync(frame);
|
||||||
|
|
||||||
|
await WaitForConnectionErrorAsync<Http2ConnectionErrorException>(
|
||||||
|
ignoreNonGoAwayFrames: true,
|
||||||
|
expectedLastStreamId: 1,
|
||||||
|
expectedErrorCode: Http2ErrorCode.FRAME_SIZE_ERROR,
|
||||||
|
expectedErrorMessage: CoreStrings.FormatHttp2ErrorFrameOverLimit(length, Http2Frame.MinAllowedMaxFrameSize));
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task DATA_Received_ReadByStream()
|
public async Task DATA_Received_ReadByStream()
|
||||||
{
|
{
|
||||||
|
|
@ -2794,7 +2816,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
{
|
{
|
||||||
Assert.True(buffer.Length > 0);
|
Assert.True(buffer.Length > 0);
|
||||||
|
|
||||||
if (Http2FrameReader.ReadFrame(buffer, frame, out consumed, out examined))
|
if (Http2FrameReader.ReadFrame(buffer, frame, 16_384, out consumed, out examined))
|
||||||
{
|
{
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue