private async Task <IAdaptedConnection> InnerOnConnectionAsync(ConnectionAdapterContext context) { SslStream sslStream; bool certificateRequired; var feature = new TlsConnectionFeature(); context.Features.Set <ITlsConnectionFeature>(feature); 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; } var timeoutFeature = context.Features.Get <IConnectionTimeoutFeature>(); timeoutFeature.SetTimeout(_options.HandshakeTimeout); try { #if NETCOREAPP2_1 var sslOptions = new SslServerAuthenticationOptions() { ServerCertificate = _serverCertificate, ClientCertificateRequired = certificateRequired, EnabledSslProtocols = _options.SslProtocols, CertificateRevocationCheckMode = _options.CheckCertificateRevocation ? X509RevocationMode.Online : X509RevocationMode.NoCheck, ApplicationProtocols = new List <SslApplicationProtocol>() }; // This is order sensitive if ((_options.HttpProtocols & HttpProtocols.Http2) != 0) { sslOptions.ApplicationProtocols.Add(SslApplicationProtocol.Http2); } if ((_options.HttpProtocols & HttpProtocols.Http1) != 0) { sslOptions.ApplicationProtocols.Add(SslApplicationProtocol.Http11); } await sslStream.AuthenticateAsServerAsync(sslOptions, CancellationToken.None); #else await sslStream.AuthenticateAsServerAsync(_serverCertificate, certificateRequired, _options.SslProtocols, _options.CheckCertificateRevocation); #endif } catch (OperationCanceledException) { _logger?.LogInformation(2, CoreStrings.AuthenticationTimedOut); sslStream.Dispose(); return(_closedAdaptedConnection); } catch (IOException ex) { _logger?.LogInformation(1, ex, CoreStrings.AuthenticationFailed); sslStream.Dispose(); return(_closedAdaptedConnection); } finally { timeoutFeature.CancelTimeout(); } #if NETCOREAPP2_1 // Don't allocate in the common case, see https://github.com/dotnet/corefx/issues/25432 if (sslStream.NegotiatedApplicationProtocol == SslApplicationProtocol.Http11) { feature.ApplicationProtocol = "http/1.1"; } else if (sslStream.NegotiatedApplicationProtocol == SslApplicationProtocol.Http2) { feature.ApplicationProtocol = "h2"; } else { feature.ApplicationProtocol = sslStream.NegotiatedApplicationProtocol.ToString(); } context.Features.Set <ITlsApplicationProtocolFeature>(feature); #endif feature.ClientCertificate = ConvertToX509Certificate2(sslStream.RemoteCertificate); return(new HttpsAdaptedConnection(sslStream)); }
private async Task <IAdaptedConnection> InnerOnConnectionAsync(ConnectionAdapterContext context) { SslStream sslStream; bool certificateRequired; var feature = new TlsConnectionFeature(); context.Features.Set <ITlsConnectionFeature>(feature); 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; } var timeoutFeature = context.Features.Get <IConnectionTimeoutFeature>(); timeoutFeature.SetTimeout(_options.HandshakeTimeout); try { #if NETCOREAPP2_1 // Adapt to the SslStream signature ServerCertificateSelectionCallback selector = null; if (_serverCertificateSelector != null) { selector = (sender, name) => { context.Features.Set(sslStream); var cert = _serverCertificateSelector(context.ConnectionContext, name); if (cert != null) { EnsureCertificateIsAllowedForServerAuth(cert); } return(cert); }; } var sslOptions = new SslServerAuthenticationOptions() { ServerCertificate = _serverCertificate, ServerCertificateSelectionCallback = selector, ClientCertificateRequired = certificateRequired, EnabledSslProtocols = _options.SslProtocols, CertificateRevocationCheckMode = _options.CheckCertificateRevocation ? X509RevocationMode.Online : X509RevocationMode.NoCheck, ApplicationProtocols = new List <SslApplicationProtocol>() }; // This is order sensitive if ((_options.HttpProtocols & HttpProtocols.Http2) != 0) { sslOptions.ApplicationProtocols.Add(SslApplicationProtocol.Http2); } if ((_options.HttpProtocols & HttpProtocols.Http1) != 0) { sslOptions.ApplicationProtocols.Add(SslApplicationProtocol.Http11); } await sslStream.AuthenticateAsServerAsync(sslOptions, CancellationToken.None); #else var serverCert = _serverCertificate; if (_serverCertificateSelector != null) { context.Features.Set(sslStream); serverCert = _serverCertificateSelector(context.ConnectionContext, null); if (serverCert != null) { EnsureCertificateIsAllowedForServerAuth(serverCert); } } await sslStream.AuthenticateAsServerAsync(serverCert, certificateRequired, _options.SslProtocols, _options.CheckCertificateRevocation); #endif } catch (OperationCanceledException) { _logger?.LogDebug(2, CoreStrings.AuthenticationTimedOut); sslStream.Dispose(); return(_closedAdaptedConnection); } catch (IOException ex) { _logger?.LogDebug(1, ex, CoreStrings.AuthenticationFailed); sslStream.Dispose(); return(_closedAdaptedConnection); } finally { timeoutFeature.CancelTimeout(); } #if NETCOREAPP2_1 feature.ApplicationProtocol = sslStream.NegotiatedApplicationProtocol.Protocol; context.Features.Set <ITlsApplicationProtocolFeature>(feature); #endif feature.ClientCertificate = ConvertToX509Certificate2(sslStream.RemoteCertificate); return(new HttpsAdaptedConnection(sslStream)); }