Skip to content
This repository has been archived by the owner on Dec 18, 2018. It is now read-only.

Commit

Permalink
Expose Tls details as a feature. #2661
Browse files Browse the repository at this point in the history
Limit Http/2 to TLS 1.2 #2251
Bootstrap functional tests #2238
  • Loading branch information
Tratcher committed Jun 13, 2018
1 parent 13663e1 commit 6e3937d
Show file tree
Hide file tree
Showing 16 changed files with 484 additions and 59 deletions.
1 change: 1 addition & 0 deletions build/dependencies.props
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
<SystemBuffersPackageVersion>4.6.0-preview1-26605-01</SystemBuffersPackageVersion>
<SystemIOPipelinesPackageVersion>4.6.0-preview1-26605-01</SystemIOPipelinesPackageVersion>
<SystemMemoryPackageVersion>4.6.0-preview1-26605-01</SystemMemoryPackageVersion>
<SystemNetHttpWinHttpHandlerPackageVersion>4.6.0-preview1-26605-01</SystemNetHttpWinHttpHandlerPackageVersion>
<SystemNumericsVectorsPackageVersion>4.6.0-preview1-26605-01</SystemNumericsVectorsPackageVersion>
<SystemRuntimeCompilerServicesUnsafePackageVersion>4.6.0-preview1-26605-01</SystemRuntimeCompilerServicesUnsafePackageVersion>
<SystemSecurityCryptographyCngPackageVersion>4.6.0-preview1-26605-01</SystemSecurityCryptographyCngPackageVersion>
Expand Down
25 changes: 25 additions & 0 deletions src/Kestrel.Core/Features/ITlsHandshakeFeature.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.Security.Authentication;

namespace Microsoft.AspNetCore.Http.Features
{
// TODO: Move to HttpAbstractions
public interface ITlsHandshakeFeature
{
SslProtocols Protocol { get; }

CipherAlgorithmType CipherAlgorithm { get; }

int CipherStrength { get; }

HashAlgorithmType HashAlgorithm { get; }

int HashStrength { get; }

ExchangeAlgorithmType KeyExchangeAlgorithm { get; }

int KeyExchangeStrength { get; }
}
}
79 changes: 54 additions & 25 deletions src/Kestrel.Core/Internal/Http2/Http2Connection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@

using System;
using System.Buffers;
using System.Collections;
using System.Collections.Concurrent;
using System.IO.Pipelines;
using System.Security.Authentication;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting.Server;
Expand Down Expand Up @@ -115,31 +115,11 @@ public async Task ProcessRequestsAsync<TContext>(IHttpApplication<TContext> appl

try
{
while (!_stopping)
{
var result = await Input.ReadAsync();
var readableBuffer = result.Buffer;
var consumed = readableBuffer.Start;
var examined = readableBuffer.End;
ValidateTlsRequirements();

try
{
if (!readableBuffer.IsEmpty)
{
if (ParsePreface(readableBuffer, out consumed, out examined))
{
break;
}
}
else if (result.IsCompleted)
{
return;
}
}
finally
{
Input.AdvanceTo(consumed, examined);
}
if (!await TryReadPrefaceAsync())
{
return;
}

if (!_stopping)
Expand Down Expand Up @@ -222,6 +202,55 @@ public async Task ProcessRequestsAsync<TContext>(IHttpApplication<TContext> appl
}
}

// https://tools.ietf.org/html/rfc7540#section-9.2
// Some of these could not be checked in advance. Fail before using the connection.
private void ValidateTlsRequirements()
{
var tlsFeature = ConnectionFeatures?.Get<ITlsHandshakeFeature>();
if (tlsFeature == null)
{
// Not using TLS at all.
return;
}

if (tlsFeature.Protocol < SslProtocols.Tls12)
{
throw new Http2ConnectionErrorException($"Tls 1.2 or later must be used. {tlsFeature.Protocol} was negotiated.", Http2ErrorCode.INADEQUATE_SECURITY);
}
}

private async Task<bool> TryReadPrefaceAsync()
{
while (!_stopping)
{
var result = await Input.ReadAsync();
var readableBuffer = result.Buffer;
var consumed = readableBuffer.Start;
var examined = readableBuffer.End;

try
{
if (!readableBuffer.IsEmpty)
{
if (ParsePreface(readableBuffer, out consumed, out examined))
{
return true;
}
}
else if (result.IsCompleted)
{
return false;
}
}
finally
{
Input.AdvanceTo(consumed, examined);
}
}

return false;
}

private bool ParsePreface(ReadOnlySequence<byte> readableBuffer, out SequencePosition consumed, out SequencePosition examined)
{
consumed = readableBuffer.Start;
Expand Down
8 changes: 8 additions & 0 deletions src/Kestrel.Core/Internal/HttpsConnectionAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ private async Task<IAdaptedConnection> InnerOnConnectionAsync(ConnectionAdapterC
bool certificateRequired;
var feature = new TlsConnectionFeature();
context.Features.Set<ITlsConnectionFeature>(feature);
context.Features.Set<ITlsHandshakeFeature>(feature);

if (_options.ClientCertificateMode == ClientCertificateMode.NoCertificate)
{
Expand Down Expand Up @@ -210,6 +211,13 @@ await sslStream.AuthenticateAsServerAsync(serverCert, certificateRequired,
#error TFMs need to be updated
#endif
feature.ClientCertificate = ConvertToX509Certificate2(sslStream.RemoteCertificate);
feature.CipherAlgorithm = sslStream.CipherAlgorithm;
feature.CipherStrength = sslStream.CipherStrength;
feature.HashAlgorithm = sslStream.HashAlgorithm;
feature.HashStrength = sslStream.HashStrength;
feature.KeyExchangeAlgorithm = sslStream.KeyExchangeAlgorithm;
feature.KeyExchangeStrength = sslStream.KeyExchangeStrength;
feature.Protocol = sslStream.SslProtocol;

return new HttpsAdaptedConnection(sslStream);
}
Expand Down
17 changes: 16 additions & 1 deletion src/Kestrel.Core/Internal/TlsConnectionFeature.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using System.Threading.Tasks;
Expand All @@ -10,12 +11,26 @@

namespace Microsoft.AspNetCore.Server.Kestrel.Https.Internal
{
internal class TlsConnectionFeature : ITlsConnectionFeature, ITlsApplicationProtocolFeature
internal class TlsConnectionFeature : ITlsConnectionFeature, ITlsApplicationProtocolFeature, ITlsHandshakeFeature
{
public X509Certificate2 ClientCertificate { get; set; }

public ReadOnlyMemory<byte> ApplicationProtocol { get; set; }

public SslProtocols Protocol { get; set; }

public CipherAlgorithmType CipherAlgorithm { get; set; }

public int CipherStrength { get; set; }

public HashAlgorithmType HashAlgorithm { get; set; }

public int HashStrength { get; set; }

public ExchangeAlgorithmType KeyExchangeAlgorithm { get; set; }

public int KeyExchangeStrength { get; set; }

public Task<X509Certificate2> GetClientCertificateAsync(CancellationToken cancellationToken)
{
return Task.FromResult(ClientCertificate);
Expand Down
8 changes: 2 additions & 6 deletions src/Kestrel.Transport.Libuv/Internal/LibuvOutputConsumer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,6 @@ public async Task WriteOutputAsync()

try
{
if (result.IsCanceled)
{
break;
}

if (!buffer.IsEmpty)
{
var writeReq = pool.Allocate();
Expand Down Expand Up @@ -89,7 +84,8 @@ public async Task WriteOutputAsync()
writeReq = null;
}
}
else if (result.IsCompleted)

if (result.IsCompleted || result.IsCanceled)
{
break;
}
Expand Down
7 changes: 1 addition & 6 deletions src/Kestrel.Transport.Sockets/Internal/SocketConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -247,11 +247,6 @@ private async Task ProcessSends()

var buffer = result.Buffer;

if (result.IsCanceled)
{
break;
}

var end = buffer.End;
var isCompleted = result.IsCompleted;
if (!buffer.IsEmpty)
Expand All @@ -265,7 +260,7 @@ private async Task ProcessSends()

Output.AdvanceTo(end);

if (isCompleted)
if (isCompleted || result.IsCanceled)
{
break;
}
Expand Down
Loading

0 comments on commit 6e3937d

Please sign in to comment.