This repository was archived by the owner on Dec 18, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 522
Create a direct way to configure endpoints on KestrelEngine #1280
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
160 changes: 160 additions & 0 deletions
160
src/Microsoft.AspNetCore.Server.Kestrel.Https/HttpsConnectionAdapter.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
// 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; | ||
using System.IO; | ||
using System.Net.Security; | ||
using System.Security.Cryptography.X509Certificates; | ||
using System.Threading.Tasks; | ||
using Microsoft.AspNetCore.Http.Features; | ||
using Microsoft.AspNetCore.Server.Kestrel.Adapter; | ||
using Microsoft.AspNetCore.Server.Kestrel.Https.Internal; | ||
using Microsoft.Extensions.Logging; | ||
|
||
namespace Microsoft.AspNetCore.Server.Kestrel.Https | ||
{ | ||
public class HttpsConnectionAdapter : IConnectionAdapter | ||
{ | ||
private static readonly ClosedAdaptedConnection _closedAdaptedConnection = new ClosedAdaptedConnection(); | ||
|
||
private readonly HttpsConnectionAdapterOptions _options; | ||
private readonly ILogger _logger; | ||
|
||
public HttpsConnectionAdapter(HttpsConnectionAdapterOptions options) | ||
: this(options, loggerFactory: null) | ||
{ | ||
} | ||
|
||
public HttpsConnectionAdapter(HttpsConnectionAdapterOptions options, ILoggerFactory loggerFactory) | ||
{ | ||
if (options == null) | ||
{ | ||
throw new ArgumentNullException(nameof(options)); | ||
} | ||
if (options.ServerCertificate == null) | ||
{ | ||
throw new ArgumentException("The server certificate parameter is required."); | ||
} | ||
|
||
_options = options; | ||
_logger = loggerFactory?.CreateLogger(nameof(HttpsConnectionAdapter)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When is the logger factory null? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When the HttpsConnectionAdapter is initialized directly using the other ctor. |
||
} | ||
|
||
public async Task<IAdaptedConnection> OnConnectionAsync(ConnectionAdapterContext context) | ||
{ | ||
SslStream sslStream; | ||
bool certificateRequired; | ||
|
||
if (_options.ClientCertificateMode == ClientCertificateMode.NoCertificate) | ||
{ | ||
sslStream = new SslStream(context.ConnectionStream); | ||
certificateRequired = false; | ||
} | ||
else | ||
{ | ||
sslStream = new SslStream(context.ConnectionStream, leaveInnerStreamOpen: false, | ||
userCertificateValidationCallback: (sender, certificate, chain, sslPolicyErrors) => | ||
{ | ||
if (certificate == null) | ||
{ | ||
return _options.ClientCertificateMode != ClientCertificateMode.RequireCertificate; | ||
} | ||
|
||
if (_options.ClientCertificateValidation == null) | ||
{ | ||
if (sslPolicyErrors != SslPolicyErrors.None) | ||
{ | ||
return false; | ||
} | ||
} | ||
|
||
var certificate2 = ConvertToX509Certificate2(certificate); | ||
if (certificate2 == null) | ||
{ | ||
return false; | ||
} | ||
|
||
if (_options.ClientCertificateValidation != null) | ||
{ | ||
if (!_options.ClientCertificateValidation(certificate2, chain, sslPolicyErrors)) | ||
{ | ||
return false; | ||
} | ||
} | ||
|
||
return true; | ||
}); | ||
|
||
certificateRequired = true; | ||
} | ||
|
||
try | ||
{ | ||
await sslStream.AuthenticateAsServerAsync(_options.ServerCertificate, certificateRequired, | ||
_options.SslProtocols, _options.CheckCertificateRevocation); | ||
} | ||
catch (IOException ex) | ||
{ | ||
_logger?.LogInformation(1, ex, "Failed to authenticate HTTPS connection."); | ||
sslStream.Dispose(); | ||
return _closedAdaptedConnection; | ||
} | ||
|
||
return new HttpsAdaptedConnection(sslStream); | ||
} | ||
|
||
private static X509Certificate2 ConvertToX509Certificate2(X509Certificate certificate) | ||
{ | ||
if (certificate == null) | ||
{ | ||
return null; | ||
} | ||
|
||
X509Certificate2 certificate2 = certificate as X509Certificate2; | ||
if (certificate2 != null) | ||
{ | ||
return certificate2; | ||
} | ||
|
||
#if NETSTANDARD1_3 | ||
// conversion X509Certificate to X509Certificate2 not supported | ||
// https://github.com/dotnet/corefx/issues/4510 | ||
return null; | ||
#else | ||
return new X509Certificate2(certificate); | ||
#endif | ||
} | ||
|
||
private class HttpsAdaptedConnection : IAdaptedConnection | ||
{ | ||
private readonly SslStream _sslStream; | ||
|
||
public HttpsAdaptedConnection(SslStream sslStream) | ||
{ | ||
_sslStream = sslStream; | ||
} | ||
|
||
public Stream ConnectionStream => _sslStream; | ||
|
||
public void PrepareRequest(IFeatureCollection requestFeatures) | ||
{ | ||
var clientCertificate = ConvertToX509Certificate2(_sslStream.RemoteCertificate); | ||
if (clientCertificate != null) | ||
{ | ||
requestFeatures.Set<ITlsConnectionFeature>(new TlsConnectionFeature { ClientCertificate = clientCertificate }); | ||
} | ||
|
||
requestFeatures.Get<IHttpRequestFeature>().Scheme = "https"; | ||
} | ||
} | ||
|
||
private class ClosedAdaptedConnection : IAdaptedConnection | ||
{ | ||
public Stream ConnectionStream { get; } = new ClosedStream(); | ||
|
||
public void PrepareRequest(IFeatureCollection requestFeatures) | ||
{ | ||
} | ||
} | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For a realistic sample the IP and port need to come from command line / env / config. We need to make that possible in one or two lines. Even if it means having a Listen overload that takes a string for
IP:port
that understands IPv4, IPv6, and *.@shirhatti
options.Listen(config["IPAndPort"], listenOptions => ...
Note IPEndpoint does not implement Parse so you can't just punt this over there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that the VS 2017 self-host profile now sets the ASPNETCORE_URLS environment variable by default so apps are unlikely to start from VS on localhost:5000 anymore. /cc: @BillHiebert