diff --git a/src/Microsoft.AspNet.Server.Kestrel/IKestrelServerInformation.cs b/src/Microsoft.AspNet.Server.Kestrel/IKestrelServerInformation.cs index 870fe2e53..e4f496944 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/IKestrelServerInformation.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/IKestrelServerInformation.cs @@ -11,6 +11,10 @@ public interface IKestrelServerInformation bool NoDelay { get; set; } + int MaxHeaderBytes { get; set; } + + long MaxUploadBytes { get; set; } + IConnectionFilter ConnectionFilter { get; set; } } } diff --git a/src/Microsoft.AspNet.Server.Kestrel/Infrastructure/MemoryPoolIterator2.cs b/src/Microsoft.AspNet.Server.Kestrel/Infrastructure/MemoryPoolIterator2.cs index 7de5c7fb1..65bb3ff89 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Infrastructure/MemoryPoolIterator2.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Infrastructure/MemoryPoolIterator2.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.IO; using System.Linq; using System.Numerics; using System.Text; @@ -26,16 +27,19 @@ public struct MemoryPoolIterator2 private MemoryPoolBlock2 _block; private int _index; + private int _processed; public MemoryPoolIterator2(MemoryPoolBlock2 block) { _block = block; _index = _block?.Start ?? 0; + _processed = 0; } public MemoryPoolIterator2(MemoryPoolBlock2 block, int index) { _block = block; _index = index; + _processed = 0; } public bool IsDefault => _block == null; @@ -170,6 +174,11 @@ public int Seek(int char0) } while (block.End != index) { + if (_processed > _maxHeaderLength) + { + throw new InvalidDataException("Malformed request"); + } + var following = block.End - index; if (following >= vectorStride) { @@ -180,6 +189,7 @@ public int Seek(int char0) if (ch0Count == 0) { index += vectorStride; + _processed += vectorStride; continue; } else if (ch0Count == 1) @@ -240,6 +250,11 @@ public int Seek(int char0, int char1) } while (block.End != index) { + if (_processed > _maxHeaderLength) + { + throw new InvalidDataException("Malformed request"); + } + var following = block.End - index; if (following >= vectorStride) { @@ -252,6 +267,7 @@ public int Seek(int char0, int char1) if (ch0Count == 0 && ch1Count == 0) { index += vectorStride; + _processed += vectorStride; continue; } else if (ch0Count < 2 && ch1Count < 2) @@ -332,6 +348,11 @@ public int Seek(int char0, int char1, int char2) } while (block.End != index) { + if (_processed > _maxHeaderLength) + { + throw new InvalidDataException("Malformed request"); + } + var following = block.End - index; if (following >= vectorStride) { @@ -346,6 +367,7 @@ public int Seek(int char0, int char1, int char2) if (ch0Count == 0 && ch1Count == 0 && ch2Count == 0) { index += vectorStride; + _processed += vectorStride; continue; } else if (ch0Count < 2 && ch1Count < 2 && ch2Count < 2) diff --git a/src/Microsoft.AspNet.Server.Kestrel/KestrelServerInformation.cs b/src/Microsoft.AspNet.Server.Kestrel/KestrelServerInformation.cs index 840533012..0cac8d1ed 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/KestrelServerInformation.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/KestrelServerInformation.cs @@ -17,6 +17,10 @@ public class KestrelServerInformation : IKestrelServerInformation, IServerAddres public bool NoDelay { get; set; } + public int MaxHeaderBytes { get; set; } = 16384; // 16kB + + public long MaxUploadBytes { get; set; } = 8388608; // 8MB + public IConnectionFilter ConnectionFilter { get; set; } public void Initialize(IConfiguration configuration) @@ -26,6 +30,36 @@ public void Initialize(IConfiguration configuration) { Addresses.Add(url); } + + var maxHeaderBytes = configuration["request.maxHeaderBytes"]; + if (!string.IsNullOrEmpty(maxHeaderBytes)) + { + int value; + if (!int.TryParse(maxHeaderBytes, out value)) + { + throw new ArgumentException("maxHeaderBytes must be an integer 1024 or greater", "request.maxHeaderBytes"); + } + if (value < 1024) + { + throw new ArgumentOutOfRangeException("request.maxHeaderBytes", maxHeaderBytes, "maxHeaderBytes must be 1024 or greater"); + } + MaxHeaderBytes = value; + } + + var maxUploadBytes = configuration["request.maxUploadBytes"]; + if (!string.IsNullOrEmpty(maxHeaderBytes)) + { + long value; + if (!long.TryParse(maxHeaderBytes, out value)) + { + throw new ArgumentException("maxUploadBytes must be an integer 0 or greater", "request.maxUploadBytes"); + } + if (value < 0) + { + throw new ArgumentOutOfRangeException("request.maxUploadBytes", maxUploadBytes, "maxUploadBytes must be a positive integer"); + } + MaxUploadBytes = value; + } } } }