Unify header rejection messages.
- Log bad headers with escaped non-vchar characters
This commit is contained in:
parent
dbcf34388e
commit
bb973decb8
|
|
@ -22,20 +22,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel
|
|||
BadHttpRequestException ex;
|
||||
switch (reason)
|
||||
{
|
||||
case RequestRejectionReason.HeadersCorruptedInvalidHeaderSequence:
|
||||
ex = new BadHttpRequestException("Headers corrupted, invalid header sequence.", StatusCodes.Status400BadRequest);
|
||||
break;
|
||||
case RequestRejectionReason.NoColonCharacterFoundInHeaderLine:
|
||||
ex = new BadHttpRequestException("No ':' character found in header line.", StatusCodes.Status400BadRequest);
|
||||
break;
|
||||
case RequestRejectionReason.WhitespaceIsNotAllowedInHeaderName:
|
||||
ex = new BadHttpRequestException("Whitespace is not allowed in header name.", StatusCodes.Status400BadRequest);
|
||||
break;
|
||||
case RequestRejectionReason.HeaderValueMustNotContainCR:
|
||||
ex = new BadHttpRequestException("Header value must not contain CR characters.", StatusCodes.Status400BadRequest);
|
||||
break;
|
||||
case RequestRejectionReason.HeaderValueLineFoldingNotSupported:
|
||||
ex = new BadHttpRequestException("Header value line folding not supported.", StatusCodes.Status400BadRequest);
|
||||
case RequestRejectionReason.InvalidRequestHeadersNoCRLF:
|
||||
ex = new BadHttpRequestException("Invalid request headers: missing final CRLF in header fields.", StatusCodes.Status400BadRequest);
|
||||
break;
|
||||
case RequestRejectionReason.InvalidRequestLine:
|
||||
ex = new BadHttpRequestException("Invalid request line.", StatusCodes.Status400BadRequest);
|
||||
|
|
@ -58,24 +46,15 @@ namespace Microsoft.AspNetCore.Server.Kestrel
|
|||
case RequestRejectionReason.ChunkedRequestIncomplete:
|
||||
ex = new BadHttpRequestException("Chunked request incomplete.", StatusCodes.Status400BadRequest);
|
||||
break;
|
||||
case RequestRejectionReason.PathContainsNullCharacters:
|
||||
ex = new BadHttpRequestException("The path contains null characters.", StatusCodes.Status400BadRequest);
|
||||
break;
|
||||
case RequestRejectionReason.InvalidCharactersInHeaderName:
|
||||
ex = new BadHttpRequestException("Invalid characters in header name.", StatusCodes.Status400BadRequest);
|
||||
break;
|
||||
case RequestRejectionReason.NonAsciiOrNullCharactersInInputString:
|
||||
ex = new BadHttpRequestException("The input string contains non-ASCII or null characters.", StatusCodes.Status400BadRequest);
|
||||
break;
|
||||
case RequestRejectionReason.RequestLineTooLong:
|
||||
ex = new BadHttpRequestException("Request line too long.", StatusCodes.Status414UriTooLong);
|
||||
break;
|
||||
case RequestRejectionReason.HeadersExceedMaxTotalSize:
|
||||
ex = new BadHttpRequestException("Request headers too long.", StatusCodes.Status431RequestHeaderFieldsTooLarge);
|
||||
break;
|
||||
case RequestRejectionReason.MissingCRInHeaderLine:
|
||||
ex = new BadHttpRequestException("No CR character found in header line.", StatusCodes.Status400BadRequest);
|
||||
break;
|
||||
case RequestRejectionReason.TooManyHeaders:
|
||||
ex = new BadHttpRequestException("Request contains too many headers.", StatusCodes.Status431RequestHeaderFieldsTooLarge);
|
||||
break;
|
||||
|
|
@ -95,7 +74,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel
|
|||
switch (reason)
|
||||
{
|
||||
case RequestRejectionReason.InvalidRequestLine:
|
||||
ex = new BadHttpRequestException($"Invalid request line: {value}", StatusCodes.Status400BadRequest);
|
||||
ex = new BadHttpRequestException($"Invalid request line: '{value}'", StatusCodes.Status400BadRequest);
|
||||
break;
|
||||
case RequestRejectionReason.InvalidRequestHeader:
|
||||
ex = new BadHttpRequestException($"Invalid request header: '{value}'", StatusCodes.Status400BadRequest);
|
||||
break;
|
||||
case RequestRejectionReason.InvalidContentLength:
|
||||
ex = new BadHttpRequestException($"Invalid content length: {value}", StatusCodes.Status400BadRequest);
|
||||
|
|
|
|||
|
|
@ -316,11 +316,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
|
|||
}
|
||||
|
||||
// Headers don't end in CRLF line.
|
||||
RejectRequest(RequestRejectionReason.HeadersCorruptedInvalidHeaderSequence);
|
||||
}
|
||||
else if(ch1 == ByteSpace || ch1 == ByteTab)
|
||||
{
|
||||
RejectRequest(RequestRejectionReason.WhitespaceIsNotAllowedInHeaderName);
|
||||
RejectRequest(RequestRejectionReason.InvalidRequestHeadersNoCRLF);
|
||||
}
|
||||
|
||||
// We moved the reader so look ahead 2 bytes so reset both the reader
|
||||
|
|
@ -390,7 +386,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
|
|||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe int FindEndOfName(byte* headerLine, int length)
|
||||
private unsafe int FindEndOfName(byte* headerLine, int length)
|
||||
{
|
||||
var index = 0;
|
||||
var sawWhitespace = false;
|
||||
|
|
@ -407,14 +403,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
|
|||
}
|
||||
}
|
||||
|
||||
if (index == length)
|
||||
if (index == length || sawWhitespace)
|
||||
{
|
||||
RejectRequest(RequestRejectionReason.NoColonCharacterFoundInHeaderLine);
|
||||
}
|
||||
if (sawWhitespace)
|
||||
{
|
||||
RejectRequest(RequestRejectionReason.WhitespaceIsNotAllowedInHeaderName);
|
||||
RejectRequestHeader(headerLine, length);
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
|
|
@ -427,11 +420,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
|
|||
|
||||
if (headerLine[valueEnd + 2] != ByteLF)
|
||||
{
|
||||
RejectRequest(RequestRejectionReason.HeaderValueMustNotContainCR);
|
||||
RejectRequestHeader(headerLine, length);
|
||||
}
|
||||
if (headerLine[valueEnd + 1] != ByteCR)
|
||||
{
|
||||
RejectRequest(RequestRejectionReason.MissingCRInHeaderLine);
|
||||
RejectRequestHeader(headerLine, length);
|
||||
}
|
||||
|
||||
// Skip colon from value start
|
||||
|
|
@ -446,16 +439,15 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
|
|||
}
|
||||
else if (ch == ByteCR)
|
||||
{
|
||||
RejectRequest(RequestRejectionReason.HeaderValueMustNotContainCR);
|
||||
RejectRequestHeader(headerLine, length);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Check for CR in value
|
||||
var i = valueStart + 1;
|
||||
if (Contains(headerLine + i, valueEnd - i, ByteCR))
|
||||
{
|
||||
RejectRequest(RequestRejectionReason.HeaderValueMustNotContainCR);
|
||||
RejectRequestHeader(headerLine, length);
|
||||
}
|
||||
|
||||
// Ignore end whitespace
|
||||
|
|
@ -557,9 +549,25 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
|
|||
Log.IsEnabled(LogLevel.Information) ? span.GetAsciiStringEscaped(MaxRequestLineError) : string.Empty);
|
||||
}
|
||||
|
||||
private unsafe void RejectRequestHeader(byte* headerLine, int length)
|
||||
{
|
||||
RejectRequestHeader(new Span<byte>(headerLine, length));
|
||||
}
|
||||
|
||||
private void RejectRequestHeader(Span<byte> span)
|
||||
{
|
||||
throw GetRejectRequestHeaderException(span);
|
||||
}
|
||||
|
||||
private BadHttpRequestException GetRejectRequestHeaderException(Span<byte> span)
|
||||
{
|
||||
const int MaxRequestHeaderError = 128;
|
||||
return BadHttpRequestException.GetException(RequestRejectionReason.InvalidRequestHeader,
|
||||
Log.IsEnabled(LogLevel.Information) ? span.GetAsciiStringEscaped(MaxRequestHeaderError) : string.Empty);
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
|
|
|
|||
|
|
@ -6,12 +6,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
|
|||
public enum RequestRejectionReason
|
||||
{
|
||||
UnrecognizedHTTPVersion,
|
||||
HeadersCorruptedInvalidHeaderSequence,
|
||||
NoColonCharacterFoundInHeaderLine,
|
||||
WhitespaceIsNotAllowedInHeaderName,
|
||||
HeaderValueMustNotContainCR,
|
||||
HeaderValueLineFoldingNotSupported,
|
||||
InvalidRequestLine,
|
||||
InvalidRequestHeader,
|
||||
InvalidRequestHeadersNoCRLF,
|
||||
MalformedRequestInvalidHeaders,
|
||||
InvalidContentLength,
|
||||
MultipleContentLengths,
|
||||
|
|
@ -19,12 +16,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
|
|||
BadChunkSuffix,
|
||||
BadChunkSizeData,
|
||||
ChunkedRequestIncomplete,
|
||||
PathContainsNullCharacters,
|
||||
InvalidCharactersInHeaderName,
|
||||
NonAsciiOrNullCharactersInInputString,
|
||||
RequestLineTooLong,
|
||||
HeadersExceedMaxTotalSize,
|
||||
MissingCRInHeaderLine,
|
||||
TooManyHeaders,
|
||||
RequestTimeout,
|
||||
FinalTransferCodingNotChunked,
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
|
||||
foreach (var requestLine in HttpParsingData.RequestLineInvalidData)
|
||||
{
|
||||
data.Add(requestLine, $"Invalid request line: {requestLine.Replace("\r", "\\x0D").Replace("\n", "\\x0A")}");
|
||||
data.Add(requestLine, $"Invalid request line: '{requestLine.Replace("\r", "\\x0D").Replace("\n", "\\x0A")}'");
|
||||
}
|
||||
|
||||
foreach (var requestLine in HttpParsingData.RequestLineWithEncodedNullCharInTargetData)
|
||||
|
|
|
|||
|
|
@ -81,25 +81,6 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
|||
_pipelineFactory.Dispose();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TakeMessageHeadersThrowsOnHeaderValueWithLineFolding_CharacterNotAvailableOnFirstAttempt()
|
||||
{
|
||||
await _input.Writer.WriteAsync(Encoding.ASCII.GetBytes("Header-1: value1\r\n"));
|
||||
|
||||
var readableBuffer = (await _input.Reader.ReadAsync()).Buffer;
|
||||
Assert.False(_frame.TakeMessageHeaders(readableBuffer, out _consumed, out _examined));
|
||||
_input.Reader.Advance(_consumed, _examined);
|
||||
|
||||
await _input.Writer.WriteAsync(Encoding.ASCII.GetBytes(" "));
|
||||
|
||||
readableBuffer = (await _input.Reader.ReadAsync()).Buffer;
|
||||
var exception = Assert.Throws<BadHttpRequestException>(() => _frame.TakeMessageHeaders(readableBuffer, out _consumed, out _examined));
|
||||
_input.Reader.Advance(_consumed, _examined);
|
||||
|
||||
Assert.Equal("Whitespace is not allowed in header name.", exception.Message);
|
||||
Assert.Equal(StatusCodes.Status400BadRequest, exception.StatusCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TakeMessageHeadersThrowsWhenHeadersExceedTotalSizeLimit()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
|||
var exception = Assert.Throws<BadHttpRequestException>(() =>
|
||||
parser.ParseRequestLine(Mock.Of<IHttpRequestLineHandler>(), buffer, out var consumed, out var examined));
|
||||
|
||||
Assert.Equal($"Invalid request line: {requestLine.Replace("\r", "\\x0D").Replace("\n", "\\x0A")}", exception.Message);
|
||||
Assert.Equal($"Invalid request line: '{requestLine.Replace("\r", "\\x0D").Replace("\n", "\\x0A")}'", exception.Message);
|
||||
Assert.Equal(StatusCodes.Status400BadRequest, (exception as BadHttpRequestException).StatusCode);
|
||||
}
|
||||
|
||||
|
|
@ -306,7 +306,12 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
|||
[MemberData(nameof(RequestHeaderInvalidData))]
|
||||
public void ParseHeadersThrowsOnInvalidRequestHeaders(string rawHeaders, string expectedExceptionMessage)
|
||||
{
|
||||
var parser = CreateParser(Mock.Of<IKestrelTrace>());
|
||||
var mockTrace = new Mock<IKestrelTrace>();
|
||||
mockTrace
|
||||
.Setup(trace => trace.IsEnabled(LogLevel.Information))
|
||||
.Returns(true);
|
||||
|
||||
var parser = CreateParser(mockTrace.Object);
|
||||
var buffer = ReadableBuffer.Create(Encoding.ASCII.GetBytes(rawHeaders));
|
||||
|
||||
var exception = Assert.Throws<BadHttpRequestException>(() =>
|
||||
|
|
|
|||
|
|
@ -203,106 +203,79 @@ namespace Microsoft.AspNetCore.Testing
|
|||
"8charact",
|
||||
};
|
||||
|
||||
public static IEnumerable<object[]> RequestHeaderInvalidData
|
||||
public static IEnumerable<object[]> RequestHeaderInvalidData => new[]
|
||||
{
|
||||
get
|
||||
{
|
||||
// Line folding
|
||||
var headersWithLineFolding = new[]
|
||||
{
|
||||
"Header: line1\r\n line2\r\n\r\n",
|
||||
"Header: line1\r\n\tline2\r\n\r\n",
|
||||
"Header: line1\r\n line2\r\n\r\n",
|
||||
"Header: line1\r\n \tline2\r\n\r\n",
|
||||
"Header: line1\r\n\t line2\r\n\r\n",
|
||||
"Header: line1\r\n\t\tline2\r\n\r\n",
|
||||
"Header: line1\r\n \t\t line2\r\n\r\n",
|
||||
"Header: line1\r\n \t \t line2\r\n\r\n",
|
||||
"Header-1: multi\r\n line\r\nHeader-2: value2\r\n\r\n",
|
||||
"Header-1: value1\r\nHeader-2: multi\r\n line\r\n\r\n",
|
||||
"Header-1: value1\r\n Header-2: value2\r\n\r\n",
|
||||
"Header-1: value1\r\n\tHeader-2: value2\r\n\r\n",
|
||||
};
|
||||
// Missing CR
|
||||
new[] { "Header: value\n\r\n", @"Invalid request header: 'Header: value\x0A'" },
|
||||
new[] { "Header-1: value1\nHeader-2: value2\r\n\r\n", @"Invalid request header: 'Header-1: value1\x0A'" },
|
||||
new[] { "Header-1: value1\r\nHeader-2: value2\n\r\n", @"Invalid request header: 'Header-2: value2\x0A'" },
|
||||
|
||||
// CR in value
|
||||
var headersWithCRInValue = new[]
|
||||
{
|
||||
"Header-1: value1\r\r\n",
|
||||
"Header-1: val\rue1\r\n",
|
||||
"Header-1: value1\rHeader-2: value2\r\n\r\n",
|
||||
"Header-1: value1\r\nHeader-2: value2\r\r\n",
|
||||
"Header-1: value1\r\nHeader-2: v\ralue2\r\n",
|
||||
"Header-1: Value__\rVector16________Vector32\r\n",
|
||||
"Header-1: Value___Vector16\r________Vector32\r\n",
|
||||
"Header-1: Value___Vector16_______\rVector32\r\n",
|
||||
"Header-1: Value___Vector16________Vector32\r\r\n",
|
||||
"Header-1: Value___Vector16________Vector32_\r\r\n",
|
||||
"Header-1: Value___Vector16________Vector32Value___Vector16_______\rVector32\r\n",
|
||||
"Header-1: Value___Vector16________Vector32Value___Vector16________Vector32\r\r\n",
|
||||
"Header-1: Value___Vector16________Vector32Value___Vector16________Vector32_\r\r\n",
|
||||
};
|
||||
// Line folding
|
||||
new[] { "Header: line1\r\n line2\r\n\r\n", @"Invalid request header: ' line2\x0D\x0A'" },
|
||||
new[] { "Header: line1\r\n\tline2\r\n\r\n", @"Invalid request header: '\x09line2\x0D\x0A'" },
|
||||
new[] { "Header: line1\r\n line2\r\n\r\n", @"Invalid request header: ' line2\x0D\x0A'" },
|
||||
new[] { "Header: line1\r\n \tline2\r\n\r\n", @"Invalid request header: ' \x09line2\x0D\x0A'" },
|
||||
new[] { "Header: line1\r\n\t line2\r\n\r\n", @"Invalid request header: '\x09 line2\x0D\x0A'" },
|
||||
new[] { "Header: line1\r\n\t\tline2\r\n\r\n", @"Invalid request header: '\x09\x09line2\x0D\x0A'" },
|
||||
new[] { "Header: line1\r\n \t\t line2\r\n\r\n", @"Invalid request header: ' \x09\x09 line2\x0D\x0A'" },
|
||||
new[] { "Header: line1\r\n \t \t line2\r\n\r\n", @"Invalid request header: ' \x09 \x09 line2\x0D\x0A'" },
|
||||
new[] { "Header-1: multi\r\n line\r\nHeader-2: value2\r\n\r\n", @"Invalid request header: ' line\x0D\x0A'" },
|
||||
new[] { "Header-1: value1\r\nHeader-2: multi\r\n line\r\n\r\n", @"Invalid request header: ' line\x0D\x0A'" },
|
||||
new[] { "Header-1: value1\r\n Header-2: value2\r\n\r\n", @"Invalid request header: ' Header-2: value2\x0D\x0A'" },
|
||||
new[] { "Header-1: value1\r\n\tHeader-2: value2\r\n\r\n", @"Invalid request header: '\x09Header-2: value2\x0D\x0A'" },
|
||||
|
||||
// Missing colon
|
||||
var headersWithMissingColon = new[]
|
||||
{
|
||||
"Header-1 value1\r\n\r\n",
|
||||
"Header-1 value1\r\nHeader-2: value2\r\n\r\n",
|
||||
"Header-1: value1\r\nHeader-2 value2\r\n\r\n",
|
||||
"\n"
|
||||
};
|
||||
// CR in value
|
||||
new[] { "Header-1: value1\r\r\n", @"Invalid request header: 'Header-1: value1\x0D\x0D\x0A'" },
|
||||
new[] { "Header-1: val\rue1\r\n", @"Invalid request header: 'Header-1: val\x0Due1\x0D\x0A'" },
|
||||
new[] { "Header-1: value1\rHeader-2: value2\r\n\r\n", @"Invalid request header: 'Header-1: value1\x0DHeader-2: value2\x0D\x0A'" },
|
||||
new[] { "Header-1: value1\r\nHeader-2: value2\r\r\n", @"Invalid request header: 'Header-2: value2\x0D\x0D\x0A'" },
|
||||
new[] { "Header-1: value1\r\nHeader-2: v\ralue2\r\n", @"Invalid request header: 'Header-2: v\x0Dalue2\x0D\x0A'" },
|
||||
new[] { "Header-1: Value__\rVector16________Vector32\r\n", @"Invalid request header: 'Header-1: Value__\x0DVector16________Vector32\x0D\x0A'" },
|
||||
new[] { "Header-1: Value___Vector16\r________Vector32\r\n", @"Invalid request header: 'Header-1: Value___Vector16\x0D________Vector32\x0D\x0A'" },
|
||||
new[] { "Header-1: Value___Vector16_______\rVector32\r\n", @"Invalid request header: 'Header-1: Value___Vector16_______\x0DVector32\x0D\x0A'" },
|
||||
new[] { "Header-1: Value___Vector16________Vector32\r\r\n", @"Invalid request header: 'Header-1: Value___Vector16________Vector32\x0D\x0D\x0A'" },
|
||||
new[] { "Header-1: Value___Vector16________Vector32_\r\r\n", @"Invalid request header: 'Header-1: Value___Vector16________Vector32_\x0D\x0D\x0A'" },
|
||||
new[] { "Header-1: Value___Vector16________Vector32Value___Vector16_______\rVector32\r\n", @"Invalid request header: 'Header-1: Value___Vector16________Vector32Value___Vector16_______\x0DVector32\x0D\x0A'" },
|
||||
new[] { "Header-1: Value___Vector16________Vector32Value___Vector16________Vector32\r\r\n", @"Invalid request header: 'Header-1: Value___Vector16________Vector32Value___Vector16________Vector32\x0D\x0D\x0A'" },
|
||||
new[] { "Header-1: Value___Vector16________Vector32Value___Vector16________Vector32_\r\r\n", @"Invalid request header: 'Header-1: Value___Vector16________Vector32Value___Vector16________Vector32_\x0D\x0D\x0A'" },
|
||||
|
||||
// Starting with whitespace
|
||||
var headersStartingWithWhitespace = new[]
|
||||
{
|
||||
" Header: value\r\n\r\n",
|
||||
"\tHeader: value\r\n\r\n",
|
||||
" Header-1: value1\r\nHeader-2: value2\r\n\r\n",
|
||||
"\tHeader-1: value1\r\nHeader-2: value2\r\n\r\n",
|
||||
};
|
||||
// Missing colon
|
||||
new[] { "Header-1 value1\r\n\r\n", @"Invalid request header: 'Header-1 value1\x0D\x0A'" },
|
||||
new[] { "Header-1 value1\r\nHeader-2: value2\r\n\r\n", @"Invalid request header: 'Header-1 value1\x0D\x0A'" },
|
||||
new[] { "Header-1: value1\r\nHeader-2 value2\r\n\r\n", @"Invalid request header: 'Header-2 value2\x0D\x0A'" },
|
||||
new[] { "\n", @"Invalid request header: '\x0A'" },
|
||||
|
||||
// Whitespace in header name
|
||||
var headersWithWithspaceInName = new[]
|
||||
{
|
||||
"Header : value\r\n\r\n",
|
||||
"Header\t: value\r\n\r\n",
|
||||
"Header\r: value\r\n\r\n",
|
||||
"Header_\rVector16: value\r\n\r\n",
|
||||
"Header__Vector16\r: value\r\n\r\n",
|
||||
"Header__Vector16_\r: value\r\n\r\n",
|
||||
"Header_\rVector16________Vector32: value\r\n\r\n",
|
||||
"Header__Vector16________Vector32\r: value\r\n\r\n",
|
||||
"Header__Vector16________Vector32_\r: value\r\n\r\n",
|
||||
"Header__Vector16________Vector32Header_\rVector16________Vector32: value\r\n\r\n",
|
||||
"Header__Vector16________Vector32Header__Vector16________Vector32\r: value\r\n\r\n",
|
||||
"Header__Vector16________Vector32Header__Vector16________Vector32_\r: value\r\n\r\n",
|
||||
"Header 1: value1\r\nHeader-2: value2\r\n\r\n",
|
||||
"Header 1 : value1\r\nHeader-2: value2\r\n\r\n",
|
||||
"Header 1\t: value1\r\nHeader-2: value2\r\n\r\n",
|
||||
"Header 1\r: value1\r\nHeader-2: value2\r\n\r\n",
|
||||
"Header-1: value1\r\nHeader 2: value2\r\n\r\n",
|
||||
"Header-1: value1\r\nHeader-2 : value2\r\n\r\n",
|
||||
"Header-1: value1\r\nHeader-2\t: value2\r\n\r\n",
|
||||
};
|
||||
// Starting with whitespace
|
||||
new[] { " Header: value\r\n\r\n", @"Invalid request header: ' Header: value\x0D\x0A'" },
|
||||
new[] { "\tHeader: value\r\n\r\n", @"Invalid request header: '\x09Header: value\x0D\x0A'" },
|
||||
new[] { " Header-1: value1\r\nHeader-2: value2\r\n\r\n", @"Invalid request header: ' Header-1: value1\x0D\x0A'" },
|
||||
new[] { "\tHeader-1: value1\r\nHeader-2: value2\r\n\r\n", @"Invalid request header: '\x09Header-1: value1\x0D\x0A'" },
|
||||
|
||||
// Headers not ending in CRLF line
|
||||
var headersNotEndingInCrLfLine = new[]
|
||||
{
|
||||
"Header-1: value1\r\nHeader-2: value2\r\n\r\r",
|
||||
"Header-1: value1\r\nHeader-2: value2\r\n\r ",
|
||||
"Header-1: value1\r\nHeader-2: value2\r\n\r \n",
|
||||
};
|
||||
// Whitespace in header name
|
||||
new[] { "Header : value\r\n\r\n", @"Invalid request header: 'Header : value\x0D\x0A'" },
|
||||
new[] { "Header\t: value\r\n\r\n", @"Invalid request header: 'Header\x09: value\x0D\x0A'" },
|
||||
new[] { "Header\r: value\r\n\r\n", @"Invalid request header: 'Header\x0D: value\x0D\x0A'" },
|
||||
new[] { "Header_\rVector16: value\r\n\r\n", @"Invalid request header: 'Header_\x0DVector16: value\x0D\x0A'" },
|
||||
new[] { "Header__Vector16\r: value\r\n\r\n", @"Invalid request header: 'Header__Vector16\x0D: value\x0D\x0A'" },
|
||||
new[] { "Header__Vector16_\r: value\r\n\r\n", @"Invalid request header: 'Header__Vector16_\x0D: value\x0D\x0A'" },
|
||||
new[] { "Header_\rVector16________Vector32: value\r\n\r\n", @"Invalid request header: 'Header_\x0DVector16________Vector32: value\x0D\x0A'" },
|
||||
new[] { "Header__Vector16________Vector32\r: value\r\n\r\n", @"Invalid request header: 'Header__Vector16________Vector32\x0D: value\x0D\x0A'" },
|
||||
new[] { "Header__Vector16________Vector32_\r: value\r\n\r\n", @"Invalid request header: 'Header__Vector16________Vector32_\x0D: value\x0D\x0A'" },
|
||||
new[] { "Header__Vector16________Vector32Header_\rVector16________Vector32: value\r\n\r\n", @"Invalid request header: 'Header__Vector16________Vector32Header_\x0DVector16________Vector32: value\x0D\x0A'" },
|
||||
new[] { "Header__Vector16________Vector32Header__Vector16________Vector32\r: value\r\n\r\n", @"Invalid request header: 'Header__Vector16________Vector32Header__Vector16________Vector32\x0D: value\x0D\x0A'" },
|
||||
new[] { "Header__Vector16________Vector32Header__Vector16________Vector32_\r: value\r\n\r\n", @"Invalid request header: 'Header__Vector16________Vector32Header__Vector16________Vector32_\x0D: value\x0D\x0A'" },
|
||||
new[] { "Header 1: value1\r\nHeader-2: value2\r\n\r\n", @"Invalid request header: 'Header 1: value1\x0D\x0A'" },
|
||||
new[] { "Header 1 : value1\r\nHeader-2: value2\r\n\r\n", @"Invalid request header: 'Header 1 : value1\x0D\x0A'" },
|
||||
new[] { "Header 1\t: value1\r\nHeader-2: value2\r\n\r\n", @"Invalid request header: 'Header 1\x09: value1\x0D\x0A'" },
|
||||
new[] { "Header 1\r: value1\r\nHeader-2: value2\r\n\r\n", @"Invalid request header: 'Header 1\x0D: value1\x0D\x0A'" },
|
||||
new[] { "Header-1: value1\r\nHeader 2: value2\r\n\r\n", @"Invalid request header: 'Header 2: value2\x0D\x0A'" },
|
||||
new[] { "Header-1: value1\r\nHeader-2 : value2\r\n\r\n", @"Invalid request header: 'Header-2 : value2\x0D\x0A'" },
|
||||
new[] { "Header-1: value1\r\nHeader-2\t: value2\r\n\r\n", @"Invalid request header: 'Header-2\x09: value2\x0D\x0A'" },
|
||||
|
||||
return new[]
|
||||
{
|
||||
Tuple.Create(headersWithLineFolding, "Whitespace is not allowed in header name."),
|
||||
Tuple.Create(headersWithCRInValue, "Header value must not contain CR characters."),
|
||||
Tuple.Create(headersWithMissingColon, "No ':' character found in header line."),
|
||||
Tuple.Create(headersStartingWithWhitespace, "Whitespace is not allowed in header name."),
|
||||
Tuple.Create(headersWithWithspaceInName, "Whitespace is not allowed in header name."),
|
||||
Tuple.Create(headersNotEndingInCrLfLine, "Headers corrupted, invalid header sequence.")
|
||||
}
|
||||
.SelectMany(t => t.Item1.Select(headers => new[] { headers, t.Item2 }));
|
||||
}
|
||||
}
|
||||
// Headers not ending in CRLF line
|
||||
new[] { "Header-1: value1\r\nHeader-2: value2\r\n\r\r", @"Invalid request headers: missing final CRLF in header fields." },
|
||||
new[] { "Header-1: value1\r\nHeader-2: value2\r\n\r ", @"Invalid request headers: missing final CRLF in header fields." },
|
||||
new[] { "Header-1: value1\r\nHeader-2: value2\r\n\r \n", @"Invalid request headers: missing final CRLF in header fields." },
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue