public async Task OnConnectionAsync(ConnectionContext context, Func <Task> next) { if (_server.ServerStore.Initialized == false) { await _server.ServerStore.InitializationCompleted.WaitAsync(); } var tlsConnectionFeature = context.Features.Get <ITlsConnectionFeature>(); X509Certificate2 certificate = null; if (tlsConnectionFeature != null) { certificate = await tlsConnectionFeature.GetClientCertificateAsync(context.ConnectionClosed); } var httpConnectionFeature = context.Features.Get <IHttpConnectionFeature>(); var authenticationStatus = _server.AuthenticateConnectionCertificate(certificate, httpConnectionFeature); // build the token context.Features.Set <IHttpAuthenticationFeature>(authenticationStatus); await next(); }
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.IsEmpty == false) { var b = result.Buffer.First.Span[0]; if (b >= 'A' && b <= 'Z') { // this is a good indication that we have been connected using HTTP, instead of HTTPS // because the first character 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.AdvanceTo(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); } } if (_server.ServerStore.Initialized == false) { await _server.ServerStore.InitializationCompleted.WaitAsync(); } var tls = context.Features.Get <ITlsConnectionFeature>(); var certificate = tls?.ClientCertificate; var conn = context.Features.Get <IHttpConnectionFeature>(); var authenticationStatus = _server.AuthenticateConnectionCertificate(certificate, conn); // build the token context.Features.Set <IHttpAuthenticationFeature>(authenticationStatus); return(connection); }
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); var info = context.Features.Get <IHttpConnectionFeature>(); if (Logger.IsInfoEnabled && authenticationStatus.Status != RavenServer.AuthenticationStatus.Allowed && authenticationStatus.Status != RavenServer.AuthenticationStatus.Operator && authenticationStatus.Status != RavenServer.AuthenticationStatus.ClusterAdmin) { Logger.Info($"Received TLS connection request from {info?.RemoteIpAddress}:{info?.RemotePort} with client certificate: {certificate?.SubjectName?.Name}. " + $"Authentication status: {authenticationStatus.Status}."); } // build the token context.Features.Set <IHttpAuthenticationFeature>(authenticationStatus); return(connection); }