public async Task <IAdaptedConnection> OnConnectionAsync(ConnectionAdapterContext context) { await Task.Yield(); return(new AdaptedConnection(new RewritingStream(context.ConnectionStream))); }
public Task <IAdaptedConnection> OnConnectionAsync(ConnectionAdapterContext context) { var adapted = new AdaptedConnection(new PassThroughStream(context.ConnectionStream)); return(Task.FromResult <IAdaptedConnection>(adapted)); }
public Task <IAdaptedConnection> OnConnectionAsync(ConnectionAdapterContext context) { _rewritingStream = new RewritingStream(context.ConnectionStream); return(Task.FromResult <IAdaptedConnection>(new AdaptedConnection(_rewritingStream))); }
public Task <IAdaptedConnection> OnConnectionAsync(ConnectionAdapterContext context) => Task.Run(() => this.InnerOnConnectionAsync(context));
async Task <IAdaptedConnection> InnerOnConnectionAsync(ConnectionAdapterContext context) { SslStream sslStream; bool certificateRequired; IList <X509Certificate2> chainElements = new List <X509Certificate2>(); if (this.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(this.options.ClientCertificateMode != ClientCertificateMode.RequireCertificate); } if (this.options.ClientCertificateValidation == null) { if (sslPolicyErrors != SslPolicyErrors.None) { return(false); } } else if (!this.options.ClientCertificateValidation(new X509Certificate2(certificate), chain, sslPolicyErrors)) { return(false); } foreach (X509ChainElement element in chain.ChainElements) { chainElements.Add(element.Certificate); } return(true); }); certificateRequired = true; } try { if (AppContext.TryGetSwitch(DisableHandshakeTimeoutSwitch, out bool handshakeDisabled) && handshakeDisabled) { await sslStream.AuthenticateAsServerAsync( this.serverCertificate, certificateRequired, this.options.SslProtocols, this.options.CheckCertificateRevocation); } else { try { Task handshakeTask = sslStream.AuthenticateAsServerAsync( this.serverCertificate, certificateRequired, this.options.SslProtocols, this.options.CheckCertificateRevocation); Task handshakeTimeoutTask = Task.Delay(HandshakeTimeout); Task firstTask = await Task.WhenAny(handshakeTask, handshakeTimeoutTask); if (firstTask == handshakeTimeoutTask) { Events.AuthenticationTimedOut(); // Observe any exception that might be raised from AuthenticateAsServerAsync after the timeout. ObserveTaskException(handshakeTask); // This will cause the request processing loop to exit immediately and close the underlying connection. sslStream.Dispose(); return(ClosedAdaptedConnectionInstance); } // Observe potential handshake failures. await handshakeTask; } catch (OperationCanceledException) { Events.AuthenticationTimedOut(); sslStream.Dispose(); return(ClosedAdaptedConnectionInstance); } } } catch (Exception) { Events.AuthenticationFailed(); sslStream.Dispose(); return(ClosedAdaptedConnectionInstance); } Events.AuthenticationSuccess(); // Always set the feature even though the cert might be null X509Certificate2 cert = sslStream.RemoteCertificate != null ? new X509Certificate2(sslStream.RemoteCertificate) : null; context.Features.Set <ITlsConnectionFeature>( new TlsConnectionFeature { ClientCertificate = cert }); context.Features.Set <ITlsConnectionFeatureExtended>( new TlsConnectionFeatureExtended { ChainElements = chainElements }); return(new HttpsAdaptedConnection(sslStream)); }
public async Task <IAdaptedConnection> OnConnectionAsync(ConnectionAdapterContext context) { await _waitingTcs.Task; return(new AdaptedConnection(context.ConnectionStream)); }
public Task <IAdaptedConnection> OnConnectionAsync(ConnectionAdapterContext context) { throw new Exception(); }
public Task <IAdaptedConnection> OnConnectionAsync(ConnectionAdapterContext context) { // Don't trust SslStream not to block. return(Task.Run(() => InnerOnConnectionAsync(context))); }
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); // https://tools.ietf.org/html/rfc7540#section-9.2.1 sslOptions.AllowRenegotiation = false; } if ((_options.HttpProtocols & HttpProtocols.Http1) != 0) { sslOptions.ApplicationProtocols.Add(SslApplicationProtocol.Http11); } await sslStream.AuthenticateAsServerAsync(sslOptions, CancellationToken.None); #elif NETSTANDARD2_0 // No ALPN support 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); #else #error TFMs need to be updated #endif } catch (OperationCanceledException) { _logger?.LogDebug(2, CoreStrings.AuthenticationTimedOut); sslStream.Dispose(); return(_closedAdaptedConnection); } catch (Exception ex) when(ex is IOException || ex is AuthenticationException) { _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); #elif NETSTANDARD2_0 // No ALPN support #else #error TFMs need to be updated #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 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)); }
public async Task <IAdaptedConnection> OnConnectionAsync(ConnectionAdapterContext context) { if (context.ConnectionStream is RawStream rs) { // here we do protocol sniffing to see if user is trying to access us via // http while we are expecting HTTPS. var input = GetInput(rs); // uses a delegate to get the private RawStream._input out // here we take advantage of the fact that Kestrel allow to get the data from the buffer // without actually consuming it var result = await input.ReadAsync(); try { if (result.Buffer.First.TryGetArray(out var bytes) && bytes.Count > 0) { var b = bytes.Array[bytes.Offset]; if (b >= 'A' && b <= 'Z') { // this is a good indication that we have been connected using HTTP, instead of HTTPS // because the first characeter is a valid ASCII value. However, in SSL2, the first bit // is always on, and in SSL 3 / TLS 1.0 - 1.2 the first byte is 22. // https://stackoverflow.com/questions/3897883/how-to-detect-an-incoming-ssl-https-handshake-ssl-wire-format context.Features.Set <IHttpAuthenticationFeature>(new RavenServer.AuthenticateConnection { WrongProtocolMessage = "Attempted to access an HTTPS server using HTTP, did you forget to change 'http://' to 'https://' ?" }); return(new SameConnectionStream(rs)); } } } finally { input.Advance(result.Buffer.Start, result.Buffer.Start); } } var connection = await _httpsConnectionAdapter.OnConnectionAsync(context); if (connection is HttpsConnectionAdapter.HttpsAdaptedConnection c) { if (c.SslProtocol != SslProtocols.Tls12) { context.Features.Set <IHttpAuthenticationFeature>(new RavenServer.AuthenticateConnection { WrongProtocolMessage = "RavenDB requires clients to connect using TLS 1.2, but the client used: '" + c.SslProtocol + "'." }); return(c); } } var tls = context.Features.Get <ITlsConnectionFeature>(); var certificate = tls?.ClientCertificate; var authenticationStatus = _server.AuthenticateConnectionCertificate(certificate); if (Logger.IsOperationsEnabled) { Logger.Operations($"Received TLS connection request with client certificate: {certificate?.SubjectName?.Name}. Authentication status: {authenticationStatus.Status}."); } // build the token context.Features.Set <IHttpAuthenticationFeature>(authenticationStatus); return(connection); }
public Task <IAdaptedConnection> OnConnectionAsync(ConnectionAdapterContext context) { var adapted = new AdaptedConnection(new LoggingStream(context.ConnectionStream, new TestApplicationErrorLogger())); return(Task.FromResult <IAdaptedConnection>(adapted)); }
private async Task <IAdaptedConnection> InnerOnConnectionAsync(ConnectionAdapterContext context) { var sslStream = new SslStream(context.ConnectionStream, leaveInnerStreamOpen: false, userCertificateValidationCallback: (sender, certificate, chain, sslPolicyErrors) => { if (certificate == null) { return(true); // we handle the error from not having certificate higher in the stack } var certificate2 = ConvertToX509Certificate2(certificate); if (certificate2 == null) { return(false); // we require to be able to convert it in all cases } // Here we are explicitly ignoring trust chain issues for client certificates // this is because we don't actually require trust, we just use the certificate // as a way to authenticate. The admin is going to tell us which specific certs // we can trust anyway, so we can ignore such errors. return(sslPolicyErrors == SslPolicyErrors.RemoteCertificateChainErrors || sslPolicyErrors == SslPolicyErrors.None); }); var timeoutFeature = context.Features.Get <Microsoft.AspNetCore.Server.Kestrel.Core.Features.IConnectionTimeoutFeature>(); timeoutFeature.SetTimeout(_options.HandshakeTimeout); try { await sslStream.AuthenticateAsServerAsync( _serverCertificate, clientCertificateRequired : true, enabledSslProtocols : SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls, checkCertificateRevocation : true); } catch (OperationCanceledException) { sslStream.Dispose(); return(_closedAdaptedConnection); } catch (IOException ex) { if (_logger.IsInfoEnabled) { _logger.Info("Failed to authenticate client", ex); } sslStream.Dispose(); return(_closedAdaptedConnection); } finally { timeoutFeature.CancelTimeout(); } // Always set the feature even though the cert might be null context.Features.Set <ITlsConnectionFeature>(new TlsConnectionFeature { ClientCertificate = ConvertToX509Certificate2(sslStream.RemoteCertificate) }); return(new HttpsAdaptedConnection(sslStream)); }
private async Task <IAdaptedConnection> InnerOnConnectionAsync(ConnectionAdapterContext context) { // We start off by handing the connection stream off to a library that can do a peek read // (which is really just doing buffering tricks, not an actual peek read). var yourClientStream = new CustomBufferedStream(context.ConnectionStream, 4096); // We then use the same lib to parse the "peeked" data and extract the SNI hostname. var clientSslHelloInfo = await SslTools.PeekClientHello(yourClientStream); switch (clientSslHelloInfo != null) { case true: { string sniHost = clientSslHelloInfo.Extensions?.FirstOrDefault(x => x.Name == "server_name")?.Data; if (string.IsNullOrEmpty(sniHost) || string.IsNullOrWhiteSpace(sniHost)) { LoggerProxy.Default.Error("Failed to extract SNI hostname."); return(s_closedConnection); } try { var sslStream = new SslStream(yourClientStream, true, (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) => { // TODO - Handle client certificates. They should be pushed to the // upstream connection eventually. if (certificate != null) { LoggerProxy.Default.Info("CLIENT CERTIFICATE AVAILABLE!!!!!!!!!!!!!"); } return(true); } ); // Spoof a cert for the extracted SNI hostname. var spoofedCert = m_certStore.GetSpoofedCertificateForHost(sniHost); try { // Try to handshake. await sslStream.AuthenticateAsServerAsync(spoofedCert, false, s_allowedTlsProtocols, false); } catch (OperationCanceledException oe) { LoggerProxy.Default.Error("Failed to complete client TLS handshake because the operation was cancelled."); LoggerProxy.Default.Error(oe); sslStream.Dispose(); return(s_closedConnection); } catch (IOException ex) { LoggerProxy.Default.Error("Failed to complete client TLS handshake because of IO exception."); LoggerProxy.Default.Error(ex); sslStream.Dispose(); return(s_closedConnection); } // Always set the feature even though the cert might be null context.Features.Set <ITlsConnectionFeature>(new TlsConnectionFeature { ClientCertificate = sslStream.RemoteCertificate != null ? sslStream.RemoteCertificate.ToV2Certificate() : null }); return(new HttpsAdaptedConnection(sslStream)); } catch (Exception err) { LoggerProxy.Default.Error("Failed to complete client TLS handshake because of unknown exception."); LoggerProxy.Default.Error(err); } return(s_closedConnection); } default: { return(s_closedConnection); } } }
public Task <IAdaptedConnection> OnConnectionAsync(ConnectionAdapterContext context) { return(Task.Run(() => InnerOnConnectionAsync(context))); }
private async Task <IAdaptedConnection> InnerOnConnectionAsync(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; } //TODO: removed this because this is not on Kestrel 2.0 //var timeoutFeature = context.Features.Get<IConnectionTimeoutFeature>(); //timeoutFeature.SetTimeout(_options.HandshakeTimeout); try { await sslStream.AuthenticateAsServerAsync(_fetcher.Certificate, certificateRequired, _options.SslProtocols, _options.CheckCertificateRevocation); } catch (OperationCanceledException) { _logger?.LogInformation(2, HttpsStrings.AuthenticationTimedOut); sslStream.Dispose(); return(_closedAdaptedConnection); } catch (IOException ex) { _logger?.LogInformation(1, ex, HttpsStrings.AuthenticationFailed); sslStream.Dispose(); return(_closedAdaptedConnection); } finally { // TODO: restore this //timeoutFeature.CancelTimeout(); } // Always set the feature even though the cert might be null context.Features.Set <ITlsConnectionFeature>(new TlsConnectionFeature { ClientCertificate = ConvertToX509Certificate2(sslStream.RemoteCertificate) }); return(new HttpsAdaptedConnection(sslStream)); }