Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
68fd1af
ENABLE_HTTP2_PLUS_CLIENT_CERT option is set for HTTP/2 requests
alnikola Feb 21, 2020
2eb56a6
UseClientCertOnHttp2_ClientCertValid_Success test
alnikola Feb 26, 2020
923f05d
HTTP2_PLUS_CLIENT_CERT option is set before openning a connection
alnikola Mar 4, 2020
5f3bc1e
Fix Windows_NT net472 build
alnikola Mar 4, 2020
72005dc
All existing WinHttpHandler tests are enabled for net472
alnikola Mar 6, 2020
1ba5d40
Manual_CertificateOnlySentWhenValid_Success works on all frameworks
alnikola Mar 6, 2020
7ca1af2
Fix build
alnikola Mar 9, 2020
2a01fc6
Fix UseClientCertOnHttp2_OSSupportsItButCertNotSet_SuccessWithOneWayA…
alnikola Mar 9, 2020
ed354d9
All HTTP 1.1 tests enabled for WinHttpHandler on all platforms
alnikola Mar 12, 2020
90051de
Tests fixed
alnikola Mar 13, 2020
2f7792f
Unsuporrted HTTP/2 tests are disabled on Win 7 and 8.1
alnikola Mar 16, 2020
ba477cd
ConditionalFact replaced with ConditionalClass
alnikola Mar 16, 2020
03d72f7
More unsupported tests skipped
alnikola Mar 16, 2020
27f2817
Suggested changes applied
alnikola Mar 16, 2020
4d1be6c
Conditional compilation replaced with extension methods
alnikola Mar 17, 2020
8b90785
Unsupported test disabled on Win7 and Win8.1
alnikola Mar 17, 2020
4b09bdd
Enable PlatformHandler_ResponseStream_Http2_Test for all frameworks
alnikola Mar 17, 2020
6d43f8c
Skipped tests marked as Conditional
alnikola Mar 17, 2020
95bb001
Lang version bumped to 8.0
alnikola Mar 17, 2020
ffe648a
Unsupported outerloop tests disabled
alnikola Mar 18, 2020
1b306d9
Tests using RemoteExecutor fixed
alnikola Mar 18, 2020
aeca683
Unsupported tests disabled
alnikola Mar 18, 2020
35ff8e5
Comments addressed
alnikola Mar 19, 2020
378234a
ConditionalTheory and ConditionalFact are set on skippable tests for …
alnikola Mar 19, 2020
885b74e
Protocol version checks fixed
alnikola Mar 19, 2020
1cf8812
PostAsync_Cancel_CancellationTokenPassedToContent marked as Condtional
alnikola Mar 19, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,11 @@ internal partial class WinHttp

public const uint WINHTTP_OPTION_ASSURED_NON_BLOCKING_CALLBACKS = 111;

public const uint WINHTTP_OPTION_ENABLE_HTTP2_PLUS_CLIENT_CERT = 161;
public const uint WINHTTP_OPTION_ENABLE_HTTP_PROTOCOL = 133;
public const uint WINHTTP_OPTION_HTTP_PROTOCOL_USED = 134;
public const uint WINHTTP_PROTOCOL_FLAG_HTTP2 = 0x1;
public const uint WINHTTP_HTTP2_PLUS_CLIENT_CERT_FLAG = 0x1;

public const uint WINHTTP_OPTION_UPGRADE_TO_WEB_SOCKET = 114;
public const uint WINHTTP_OPTION_WEB_SOCKET_CLOSE_TIMEOUT = 115;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,8 @@ private async Task ProcessRequests()

// Send a response in the JSON format that the client expects
string username = context.User.Identity.Name;
await context.Response.OutputStream.WriteAsync(System.Text.Encoding.UTF8.GetBytes($"{{\"authenticated\": \"true\", \"user\": \"{username}\" }}"));
byte[] bytes = System.Text.Encoding.UTF8.GetBytes($"{{\"authenticated\": \"true\", \"user\": \"{username}\" }}");
await context.Response.OutputStream.WriteAsync(bytes);

context.Response.Close();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public class GenericLoopbackOptions
public IPAddress Address { get; set; } = IPAddress.Loopback;
public bool UseSsl { get; set; } = PlatformDetection.SupportsAlpn && !Capability.Http2ForceUnencryptedLoopback();
public SslProtocols SslProtocols { get; set; } =
#if !NETSTANDARD2_0
#if !NETSTANDARD2_0 && !NETFRAMEWORK
SslProtocols.Tls13 |
#endif
SslProtocols.Tls12;
Expand Down
6 changes: 4 additions & 2 deletions src/libraries/Common/tests/System/Net/Http/Http2Frames.cs
Original file line number Diff line number Diff line change
Expand Up @@ -548,10 +548,12 @@ public override void WriteTo(Span<byte> buffer)
BinaryPrimitives.WriteUInt16BigEndian(buffer, checked((ushort)Origin.Length));
buffer = buffer.Slice(2);

Encoding.ASCII.GetBytes(Origin, buffer);
var tmpBuffer = Encoding.ASCII.GetBytes(Origin);
tmpBuffer.CopyTo(buffer);
buffer = buffer.Slice(Origin.Length);

Encoding.ASCII.GetBytes(AltSvc, buffer);
tmpBuffer = Encoding.ASCII.GetBytes(AltSvc);
tmpBuffer.CopyTo(buffer);
}

public override string ToString() => $"{base.ToString()}\n{nameof(Origin)}: {Origin}\n{nameof(AltSvc)}: {AltSvc}";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
// See the LICENSE file in the project root for more information.

using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Http.Functional.Tests;
using System.Net.Security;
using System.Net.Sockets;
Expand All @@ -28,6 +28,7 @@ public class Http2LoopbackConnection : GenericLoopbackConnection
private readonly byte[] _prefix;
public string PrefixString => Encoding.UTF8.GetString(_prefix, 0, _prefix.Length);
public bool IsInvalid => _connectionSocket == null;
public Stream Stream => _connectionStream;

public Http2LoopbackConnection(Socket socket, Http2Options httpOptions)
{
Expand All @@ -40,6 +41,7 @@ public Http2LoopbackConnection(Socket socket, Http2Options httpOptions)

using (var cert = Configuration.Certificates.GetServerCertificate())
{
#if !NETFRAMEWORK
SslServerAuthenticationOptions options = new SslServerAuthenticationOptions();

options.EnabledSslProtocols = httpOptions.SslProtocols;
Expand All @@ -51,9 +53,12 @@ public Http2LoopbackConnection(Socket socket, Http2Options httpOptions)

options.ServerCertificate = cert;

options.ClientCertificateRequired = false;
options.ClientCertificateRequired = httpOptions.ClientCertificateRequired;

sslStream.AuthenticateAsServerAsync(options, CancellationToken.None).Wait();
#else
sslStream.AuthenticateAsServerAsync(cert, httpOptions.ClientCertificateRequired, httpOptions.SslProtocols, checkCertificateRevocation: false).Wait();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does WinHTTP ignore ALPN?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems - yes.

#endif
}

_connectionStream = sslStream;
Expand All @@ -64,6 +69,10 @@ public Http2LoopbackConnection(Socket socket, Http2Options httpOptions)
{
throw new Exception("Connection stream closed while attempting to read connection preface.");
}
else if (Text.Encoding.ASCII.GetString(_prefix).Contains("HTTP/1.1"))
{
throw new Exception("HTTP 1.1 request received.");
}
}

public async Task SendConnectionPrefaceAsync()
Expand Down Expand Up @@ -331,7 +340,7 @@ private static (int bytesConsumed, string value) DecodeString(ReadOnlySpan<byte>
}
else
{
string value = Encoding.ASCII.GetString(headerBlock.Slice(bytesConsumed, stringLength));
string value = Encoding.ASCII.GetString(headerBlock.Slice(bytesConsumed, stringLength).ToArray());
return (bytesConsumed + stringLength, value);
}
}
Expand Down
18 changes: 15 additions & 3 deletions src/libraries/Common/tests/System/Net/Http/Http2LoopbackServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,14 @@ public override async Task AcceptConnectionAsync(Func<GenericLoopbackConnection,
}
}

public static async Task CreateClientAndServerAsync(Func<Uri, Task> clientFunc, Func<Http2LoopbackServer, Task> serverFunc, int timeout = 60_000)
public static Task CreateClientAndServerAsync(Func<Uri, Task> clientFunc, Func<Http2LoopbackServer, Task> serverFunc, int timeout = 60_000)
{
using (var server = Http2LoopbackServer.CreateServer())
return CreateClientAndServerAsync(clientFunc, serverFunc, null, timeout);
}

public static async Task CreateClientAndServerAsync(Func<Uri, Task> clientFunc, Func<Http2LoopbackServer, Task> serverFunc, Http2Options http2Options, int timeout = 60_000)
{
using (var server = Http2LoopbackServer.CreateServer(http2Options ?? new Http2Options()))
{
Task clientTask = clientFunc(server.Address);
Task serverTask = serverFunc(server);
Expand All @@ -197,6 +202,8 @@ public class Http2Options : GenericLoopbackOptions
{
public int ListenBacklog { get; set; } = 1;

public bool ClientCertificateRequired { get; set; }

public Http2Options()
{
UseSsl = PlatformDetection.SupportsAlpn && !Capability.Http2ForceUnencryptedLoopback();
Expand Down Expand Up @@ -237,7 +244,7 @@ public override async Task CreateServerAsync(Func<GenericLoopbackServer, Uri, Ta
}
}

public override Version Version => HttpVersion.Version20;
public override Version Version => HttpVersion20.Value;
}

public enum ProtocolErrors
Expand All @@ -257,4 +264,9 @@ public enum ProtocolErrors
INADEQUATE_SECURITY = 0xc,
HTTP_1_1_REQUIRED = 0xd
}

public static class HttpVersion20
{
public static readonly Version Value = new Version(2, 0);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,10 @@ public void SingletonReturnsTrue()
[InlineData(SslProtocols.Tls, true)]
[InlineData(SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls, false)]
[InlineData(SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls, true)]
#if !NETFRAMEWORK
[InlineData(SslProtocols.Tls13 | SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls, false)]
[InlineData(SslProtocols.Tls13 | SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls, true)]
#endif
[InlineData(SslProtocols.None, false)]
[InlineData(SslProtocols.None, true)]
public async Task SetDelegate_ConnectionSucceeds(SslProtocols acceptedProtocol, bool requestOnlyThisProtocol)
Expand All @@ -64,7 +66,11 @@ public async Task SetDelegate_ConnectionSucceeds(SslProtocols acceptedProtocol,
// restrictions on minimum TLS/SSL version
// We currently know that some platforms like Debian 10 OpenSSL
// will by default block < TLS 1.2
#if !NETFRAMEWORK
handler.SslProtocols = SslProtocols.Tls13 | SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls;
#else
handler.SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls;
#endif
}

var options = new LoopbackServer.Options { UseSsl = true, SslProtocols = acceptedProtocol };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,12 @@ public async Task Credentials_ServerUsesWindowsAuthentication_Success(string ser
[InlineData("Negotiate")]
public async Task Credentials_ServerChallengesWithWindowsAuth_ClientSendsWindowsAuthHeader(string authScheme)
{
#if WINHTTPHANDLER_TEST
if (UseVersion > HttpVersion.Version11)
{
throw new SkipTestException($"Test doesn't support {UseVersion} protocol.");
}
#endif
await LoopbackServerFactory.CreateClientAndServerAsync(
async uri =>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,24 @@ public abstract class HttpClientHandler_Cancellation_Test : HttpClientHandlerTes
{
public HttpClientHandler_Cancellation_Test(ITestOutputHelper output) : base(output) { }

[Theory]
[ConditionalTheory]
[InlineData(false, CancellationMode.Token)]
[InlineData(true, CancellationMode.Token)]
public async Task PostAsync_CancelDuringRequestContentSend_TaskCanceledQuickly(bool chunkedTransfer, CancellationMode mode)
{
if (LoopbackServerFactory.Version >= HttpVersion.Version20 && chunkedTransfer)
if (LoopbackServerFactory.Version >= HttpVersion20.Value && chunkedTransfer)
{
// There is no chunked encoding in HTTP/2 and later
return;
}

#if WINHTTPHANDLER_TEST
if (UseVersion >= HttpVersion20.Value)
{
throw new SkipTestException($"Test doesn't support {UseVersion} protocol.");
}
#endif

var serverRelease = new TaskCompletionSource<bool>();
await LoopbackServerFactory.CreateClientAndServerAsync(async uri =>
{
Expand Down Expand Up @@ -76,16 +83,23 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri =>
});
}

[Theory]
[ConditionalTheory]
[MemberData(nameof(OneBoolAndCancellationMode))]
public async Task GetAsync_CancelDuringResponseHeadersReceived_TaskCanceledQuickly(bool connectionClose, CancellationMode mode)
{
if (LoopbackServerFactory.Version >= HttpVersion.Version20 && connectionClose)
if (LoopbackServerFactory.Version >= HttpVersion20.Value && connectionClose)
{
// There is no Connection header in HTTP/2 and later
return;
}

#if WINHTTPHANDLER_TEST
if (UseVersion >= HttpVersion20.Value)
{
throw new SkipTestException($"Test doesn't support {UseVersion} protocol.");
}
#endif

using (HttpClient client = CreateHttpClient())
{
client.Timeout = Timeout.InfiniteTimeSpan;
Expand Down Expand Up @@ -130,7 +144,7 @@ await ValidateClientCancellationAsync(async () =>
[MemberData(nameof(TwoBoolsAndCancellationMode))]
public async Task GetAsync_CancelDuringResponseBodyReceived_Buffered_TaskCanceledQuickly(bool chunkedTransfer, bool connectionClose, CancellationMode mode)
{
if (LoopbackServerFactory.Version >= HttpVersion.Version20 && (chunkedTransfer || connectionClose))
if (LoopbackServerFactory.Version >= HttpVersion20.Value && (chunkedTransfer || connectionClose))
{
// There is no chunked encoding or connection header in HTTP/2 and later
return;
Expand Down Expand Up @@ -182,16 +196,23 @@ await ValidateClientCancellationAsync(async () =>
}
}

[Theory]
[ConditionalTheory]
[MemberData(nameof(ThreeBools))]
public async Task GetAsync_CancelDuringResponseBodyReceived_Unbuffered_TaskCanceledQuickly(bool chunkedTransfer, bool connectionClose, bool readOrCopyToAsync)
{
if (LoopbackServerFactory.Version >= HttpVersion.Version20 && (chunkedTransfer || connectionClose))
if (LoopbackServerFactory.Version >= HttpVersion20.Value && (chunkedTransfer || connectionClose))
{
// There is no chunked encoding or connection header in HTTP/2 and later
return;
}

#if WINHTTPHANDLER_TEST
if (UseVersion >= HttpVersion20.Value)
{
throw new SkipTestException($"Test doesn't support {UseVersion} protocol.");
}
#endif

using (HttpClient client = CreateHttpClient())
{
client.Timeout = Timeout.InfiniteTimeSpan;
Expand Down Expand Up @@ -237,14 +258,19 @@ await ValidateClientCancellationAsync(async () =>
});
}
}

[Theory]
[ConditionalTheory]
[InlineData(CancellationMode.CancelPendingRequests, false)]
[InlineData(CancellationMode.DisposeHttpClient, false)]
[InlineData(CancellationMode.CancelPendingRequests, true)]
[InlineData(CancellationMode.DisposeHttpClient, true)]
public async Task GetAsync_CancelPendingRequests_DoesntCancelReadAsyncOnResponseStream(CancellationMode mode, bool copyToAsync)
{
#if WINHTTPHANDLER_TEST
if (UseVersion >= HttpVersion20.Value)
{
throw new SkipTestException($"Test doesn't support {UseVersion} protocol.");
}
#endif
using (HttpClient client = CreateHttpClient())
{
client.Timeout = Timeout.InfiniteTimeSpan;
Expand Down Expand Up @@ -312,7 +338,7 @@ await LoopbackServerFactory.CreateServerAsync(async (server, url) =>
[ConditionalFact]
public async Task MaxConnectionsPerServer_WaitingConnectionsAreCancelable()
{
if (LoopbackServerFactory.Version >= HttpVersion.Version20)
if (LoopbackServerFactory.Version >= HttpVersion20.Value)
{
// HTTP/2 does not use connection limits.
throw new SkipTestException("Not supported on HTTP/2 and later");
Expand Down Expand Up @@ -490,11 +516,18 @@ public static IEnumerable<object[]> PostAsync_Cancel_CancellationTokenPassedToCo
}
}

#if !NETFRAMEWORK
[OuterLoop("Uses Task.Delay")]
[Theory]
[ConditionalTheory]
[MemberData(nameof(PostAsync_Cancel_CancellationTokenPassedToContent_MemberData))]
public async Task PostAsync_Cancel_CancellationTokenPassedToContent(HttpContent content, CancellationTokenSource cancellationTokenSource)
{
#if WINHTTPHANDLER_TEST
if (UseVersion > HttpVersion.Version11)
{
throw new SkipTestException($"Test doesn't support {UseVersion} protocol.");
}
#endif
await LoopbackServerFactory.CreateClientAndServerAsync(
async uri =>
{
Expand All @@ -518,6 +551,7 @@ await LoopbackServerFactory.CreateClientAndServerAsync(
catch (Exception) { }
});
}
#endif

private async Task ValidateClientCancellationAsync(Func<Task> clientBodyAsync)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ await TestHelper.WhenAllCompletedOrAnyFailed(
{
_output.WriteLine(
"Client cert: {0}",
((X509Certificate2)sslStream.RemoteCertificate).GetNameInfo(X509NameType.SimpleName, false));
new X509Certificate2(sslStream.RemoteCertificate.Export(X509ContentType.Cert)).GetNameInfo(X509NameType.SimpleName, false));
Assert.Equal(cert, sslStream.RemoteCertificate);
}
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,11 @@ await LoopbackServerFactory.CreateClientAndServerAsync(

private string GetCookieValue(HttpRequestData request)
{
#if !NETFRAMEWORK
if (LoopbackServerFactory.Version < HttpVersion.Version20)
#else
if (LoopbackServerFactory.Version < HttpVersion20.Value)
#endif
{
// HTTP/1.x must have only one value.
return request.GetSingleHeaderValue("Cookie");
Expand Down Expand Up @@ -603,7 +607,9 @@ public static IEnumerable<object[]> CookieNamesValuesAndUseCookies()
yield return new object[] { "ABC", "123", useCookies };
yield return new object[] { "Hello", "World", useCookies };
yield return new object[] { "foo", "bar", useCookies };
#if !NETFRAMEWORK
yield return new object[] { "Hello World", "value", useCookies };
#endif
yield return new object[] { ".AspNetCore.Session", "RAExEmXpoCbueP_QYM", useCookies };

yield return new object[]
Expand Down
Loading