public ClientHandshakeSession(SecurityParameters securityParameters) : base(securityParameters) { if (securityParameters.ServerCertificateValidationCallback != null) { _certificateValidationCallback = securityParameters.ServerCertificateValidationCallback; } else { _certificateValidationCallback = new ServerCertificateValidationCallback(DefaultCertificateValidationCallback); } if (securityParameters.ClientCertificateSelectionCallback != null) { _certificateSelectionCallback = securityParameters.ClientCertificateSelectionCallback; } else { _certificateSelectionCallback = new ClientCertificateSelectionCallback(DefaultCertificateSelectionCallback); } HandshakeClientHello clientHello = new HandshakeClientHello(_maxVersion); clientHello.CipherSuites.AddRange(_supportedCipherSuites); clientHello.CompressionMethods.AddRange(_supportedCompressions); clientHello.Extensions.Add(new HelloSignatureAlgorithmsExtension(_pluginManager.GetSupportedSignatureAndHashAlgorithms())); OutputMessage(clientHello); _connectionState.ClientRandom = clientHello.Random.GetBytes(); }
/// <summary> /// Call back to select client certificate used for mutual authentication /// </summary> /// <param name="sender"></param> /// <param name="targetHost"></param> /// <param name="localCertificates"></param> /// <param name="remoteCertificate"></param> /// <param name="acceptableIssuers"></param> /// <returns></returns> internal X509Certificate SelectClientCertificate( object sender, string targetHost, X509CertificateCollection localCertificates, X509Certificate remoteCertificate, string[] acceptableIssuers) { X509Certificate clientCertificate = null; if (acceptableIssuers != null && acceptableIssuers.Length > 0 && localCertificates != null && localCertificates.Count > 0) { // Use the first certificate that is from an acceptable issuer. foreach (X509Certificate certificate in localCertificates) { string issuer = certificate.Issuer; if (Array.IndexOf(acceptableIssuers, issuer) != -1) { clientCertificate = certificate; } } } if (localCertificates != null && localCertificates.Count > 0) { clientCertificate = localCertificates[0]; } //If user call back is registered if (ClientCertificateSelectionCallback != null) { var args = new CertificateSelectionEventArgs { TargetHost = targetHost, LocalCertificates = localCertificates, RemoteCertificate = remoteCertificate, AcceptableIssuers = acceptableIssuers, ClientCertificate = clientCertificate }; Delegate[] invocationList = ClientCertificateSelectionCallback.GetInvocationList(); Task[] handlerTasks = new Task[invocationList.Length]; for (int i = 0; i < invocationList.Length; i++) { handlerTasks[i] = ((Func <object, CertificateSelectionEventArgs, Task>)invocationList[i])(null, args); } Task.WhenAll(handlerTasks).Wait(); return(args.ClientCertificate); } return(clientCertificate); }
/// <summary> /// Call back to select client certificate used for mutual authentication /// </summary> /// <param name="sender"></param> /// <param name="targetHost"></param> /// <param name="localCertificates"></param> /// <param name="remoteCertificate"></param> /// <param name="acceptableIssuers"></param> /// <returns></returns> internal X509Certificate SelectClientCertificate( object sender, string targetHost, X509CertificateCollection localCertificates, X509Certificate remoteCertificate, string[] acceptableIssuers) { X509Certificate clientCertificate = null; if (acceptableIssuers != null && acceptableIssuers.Length > 0 && localCertificates != null && localCertificates.Count > 0) { // Use the first certificate that is from an acceptable issuer. foreach (X509Certificate certificate in localCertificates) { string issuer = certificate.Issuer; if (Array.IndexOf(acceptableIssuers, issuer) != -1) { clientCertificate = certificate; } } } if (localCertificates != null && localCertificates.Count > 0) { clientCertificate = localCertificates[0]; } //If user call back is registered if (ClientCertificateSelectionCallback != null) { var args = new CertificateSelectionEventArgs { TargetHost = targetHost, LocalCertificates = localCertificates, RemoteCertificate = remoteCertificate, AcceptableIssuers = acceptableIssuers, ClientCertificate = clientCertificate }; //why is the sender null? ClientCertificateSelectionCallback.InvokeParallel(this, args); return(args.ClientCertificate); } return(clientCertificate); }
/// <summary> /// Call back to select client certificate used for mutual authentication /// </summary> /// <param name="sender">The sender.</param> /// <param name="sessionArgs">The http session.</param> /// <param name="targetHost">The remote hostname.</param> /// <param name="localCertificates">Selected local certificates by SslStream.</param> /// <param name="remoteCertificate">The remote certificate of server.</param> /// <param name="acceptableIssuers">The acceptable issues for client certificate as listed by server.</param> /// <returns></returns> internal X509Certificate?SelectClientCertificate(object sender, SessionEventArgsBase sessionArgs, string targetHost, X509CertificateCollection localCertificates, X509Certificate remoteCertificate, string[] acceptableIssuers) { X509Certificate?clientCertificate = null; //fallback to the first client certificate from proxy machine certificate store if (acceptableIssuers != null && acceptableIssuers.Length > 0 && localCertificates != null && localCertificates.Count > 0) { foreach (var certificate in localCertificates) { string issuer = certificate.Issuer; if (Array.IndexOf(acceptableIssuers, issuer) != -1) { clientCertificate = certificate; } } } //fallback to the first client certificate from proxy machine certificate store if (clientCertificate == null && localCertificates != null && localCertificates.Count > 0) { clientCertificate = localCertificates[0]; } // If user call back is registered if (ClientCertificateSelectionCallback != null) { var args = new CertificateSelectionEventArgs(sessionArgs, targetHost, localCertificates, remoteCertificate, acceptableIssuers) { ClientCertificate = clientCertificate }; ClientCertificateSelectionCallback.InvokeAsync(this, args, ExceptionFunc).Wait(); return(args.ClientCertificate); } return(clientCertificate); }
public ClientHandshakeSession(SecurityParameters securityParameters) : base(securityParameters) { if (securityParameters.ServerCertificateValidationCallback != null) { _certificateValidationCallback = securityParameters.ServerCertificateValidationCallback; } else { _certificateValidationCallback = new ServerCertificateValidationCallback(DefaultCertificateValidationCallback); } if (securityParameters.ClientCertificateSelectionCallback != null) { _certificateSelectionCallback = securityParameters.ClientCertificateSelectionCallback; } else { _certificateSelectionCallback = new ClientCertificateSelectionCallback(DefaultCertificateSelectionCallback); } HandshakeClientHello clientHello = new HandshakeClientHello(_maxVersion); clientHello.CipherSuites.AddRange(_supportedCipherSuites); clientHello.CompressionMethods.AddRange(_supportedCompressions); clientHello.Extensions.Add(new HelloSignatureAlgorithmsExtension(_pluginManager.GetSupportedSignatureAndHashAlgorithms())); OutputMessage(clientHello); _connectionState.ClientRandom = clientHello.Random.GetBytes(); }
/// <summary> /// Call back to select client certificate used for mutual authentication /// </summary> /// <param name="sender">The sender.</param> /// <param name="sessionArgs">The http session.</param> /// <param name="targetHost">The remote hostname.</param> /// <param name="localCertificates">Selected local certificates by SslStream.</param> /// <param name="remoteCertificate">The remote certificate of server.</param> /// <param name="acceptableIssuers">The acceptable issues for client certificate as listed by server.</param> /// <returns></returns> internal X509Certificate?SelectClientCertificate(RequestStateBase state, object sender, string targetHost, X509CertificateCollection localCertificates, X509Certificate remoteCertificate, string[] acceptableIssuers) { X509Certificate?clientCertificate = null; if (acceptableIssuers != null && acceptableIssuers.Length > 0 && localCertificates != null && localCertificates.Count > 0) { foreach (var certificate in localCertificates) { string issuer = certificate.Issuer; if (Array.IndexOf(acceptableIssuers, issuer) != -1) { clientCertificate = certificate; } } } if (localCertificates != null && localCertificates.Count > 0) { clientCertificate = localCertificates[0]; } // If user call back is registered if (ClientCertificateSelectionCallback != null) { var args = new CertificateSelectionEventArgs(state) { ClientCertificate = clientCertificate }; // why is the sender null? ClientCertificateSelectionCallback.InvokeAsync(this, args, ExceptionFunc).Wait(); return(args.ClientCertificate); } return(clientCertificate); }
/// <summary> /// Invocator for ClientCertifcateSelectionCallback event. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected virtual void OnClientCertificateSelectionCallback(object sender, CertificateSelectionEventArgs e) { ClientCertificateSelectionCallback?.Invoke(sender, e); }
private async Task InnerOnConnectionAsync(ConnectionContext context) { var feature = new TlsConnectionFeature(); context.Features.Set <ITlsConnectionFeature>(feature); context.Features.Set <ITlsHandshakeFeature>(feature); var memoryPool = context.Features.Get <IMemoryPoolFeature>()?.MemoryPool; var inputPipeOptions = new StreamPipeReaderOptions ( pool: memoryPool, bufferSize: memoryPool.GetMinimumSegmentSize(), minimumReadSize: memoryPool.GetMinimumAllocSize(), leaveOpen: true ); var outputPipeOptions = new StreamPipeWriterOptions ( pool: memoryPool, leaveOpen: true ); TlsDuplexPipe tlsDuplexPipe = null; if (_options.RemoteCertificateMode == RemoteCertificateMode.NoCertificate) { tlsDuplexPipe = new TlsDuplexPipe(context.Transport, inputPipeOptions, outputPipeOptions); } else { tlsDuplexPipe = new TlsDuplexPipe(context.Transport, inputPipeOptions, outputPipeOptions, s => new SslStream( s, leaveInnerStreamOpen: false, userCertificateValidationCallback: (sender, certificate, chain, sslPolicyErrors) => { if (certificate == null) { return(_options.RemoteCertificateMode != RemoteCertificateMode.RequireCertificate); } if (_options.RemoteCertificateValidation == null) { if (sslPolicyErrors != SslPolicyErrors.None) { return(false); } } var certificate2 = ConvertToX509Certificate2(certificate); if (certificate2 == null) { return(false); } if (_options.RemoteCertificateValidation != null) { if (!_options.RemoteCertificateValidation(certificate2, chain, sslPolicyErrors)) { return(false); } } return(true); })); } var sslStream = tlsDuplexPipe.Stream; using (var cancellationTokeSource = new CancellationTokenSource(_options.HandshakeTimeout)) using (cancellationTokeSource.Token.UnsafeRegister(state => ((ConnectionContext)state).Abort(), context)) { try { ClientCertificateSelectionCallback selector = null; if (_certificateSelector != null) { selector = (sender, targetHost, localCertificates, remoteCertificate, acceptableIssuers) => { var cert = _certificateSelector(sender, targetHost, localCertificates, remoteCertificate, acceptableIssuers); if (cert != null) { EnsureCertificateIsAllowedForClientAuth(cert); } return(cert); }; } var sslOptions = new TlsClientAuthenticationOptions { ClientCertificates = _certificate == null || _certificateSelector != null ? null : new X509CertificateCollection { _certificate }, LocalCertificateSelectionCallback = selector, EnabledSslProtocols = _options.SslProtocols, }; _options.OnAuthenticateAsClient?.Invoke(context, sslOptions); await sslStream.AuthenticateAsClientAsync(sslOptions.Value, cancellationTokeSource.Token); } catch (OperationCanceledException ex) { _logger?.LogWarning(2, ex, "Authentication timed out"); await sslStream.DisposeAsync(); return; } catch (Exception ex) { _logger?.LogWarning(1, ex, "Authentication failed"); await sslStream.DisposeAsync(); return; } } feature.ApplicationProtocol = sslStream.NegotiatedApplicationProtocol.Protocol; context.Features.Set <ITlsApplicationProtocolFeature>(feature); feature.LocalCertificate = ConvertToX509Certificate2(sslStream.LocalCertificate); feature.RemoteCertificate = 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; var originalTransport = context.Transport; try { context.Transport = tlsDuplexPipe; // Disposing the stream will dispose the tlsDuplexPipe await using (sslStream) await using (tlsDuplexPipe) { await _next(context); // Dispose the inner stream (tlsDuplexPipe) before disposing the SslStream // as the duplex pipe can hit an ODE as it still may be writing. } } finally { // Restore the original so that it gets closed appropriately context.Transport = originalTransport; } }
public ClientHandshakeSession(SecurityParameters securityParameters, ILogger logger = null) : base(securityParameters, logger) { if (securityParameters.ServerCertificateValidationCallback != null) { _certificateValidationCallback = securityParameters.ServerCertificateValidationCallback; } else { _certificateValidationCallback = new ServerCertificateValidationCallback(DefaultCertificateValidationCallback); } if (securityParameters.ClientCertificateSelectionCallback != null) { _certificateSelectionCallback = securityParameters.ClientCertificateSelectionCallback; } else { _certificateSelectionCallback = new ClientCertificateSelectionCallback(DefaultCertificateSelectionCallback); } var clientHello = new HandshakeClientHello(_maxVersion); // add ciphersuites clientHello.CipherSuites.AddRange(_supportedCipherSuites.Select(cs => (CipherSuiteId)cs)); // add compressions clientHello.CompressionMethods.AddRange(_supportedCompressions); // add signature and hash algorithms //var sigHashAlgorithms = _pluginManager.GetSupportedSignatureAndHashAlgorithms(); //clientHello.Extensions.Add(new HelloSignatureAlgorithmsExtension(new[] { (ushort)0x0403 })); clientHello.Extensions.Add(new HelloSignatureAlgorithmsExtension(new[] { new SignatureAndHashAlgorithm() { HashAlgorithm = HashAlgorithmType.Sha256, SignatureAlgorithm = SignatureAlgorithmType.Ecdsa } })); //if (sigHashAlgorithms.Any(s => BitConverter.GetBytes(s)[0] == 0x03)) //{ // clientHello.Extensions.Add(new HelloEccExtension(0x0000)); //} // get curve name from client certificate, only add the Curve Extension that corresponds to the client certificate // otherwise the meter may take the curve from the first transmitted extension (ignoring the curve of the certificate) var cert = securityParameters.AvailableCertificates.First()[0]; var data = Asn1Object.FromByteArray(cert.GetKeyAlgorithmParameters()); this.logger?.Debug($"Client certificate's key algorithm parameters {data}, here an OID is expepcted"); var oid = new DerObjectIdentifier(data.ToString()); var curveName = Org.BouncyCastle.Asn1.Sec.SecNamedCurves.GetName(oid); if (curveName.ToUpperInvariant() == "SECP256R1") { clientHello.Extensions.Add(new HelloEccExtension(EccNamedCurve.Secp256R1)); } else if (curveName.ToUpperInvariant() == "BRAINPOOLP256R1") { clientHello.Extensions.Add(new HelloEccExtension(EccNamedCurve.BrainpoolP256R1)); } else { throw new NotSupportedException($"ECC Curve {curveName} is not supported"); } this.logger?.Debug($"Creating ClientHello with max version {_maxVersion}, " + $"supported cipher suites {string.Join(",", _supportedCipherSuites.Select(cs => $"{cs:X2}"))}, " + $"compression methods {string.Join(",", _supportedCompressions.Select(c => $"{c:X2}"))}, " + $"extension {string.Join(",", clientHello.Extensions.Select(ex => ex))} "); this.OutputMessage(clientHello); _connectionState.ClientRandom = clientHello.Random.GetBytes(); }
public ClientHandshakeSession(SecurityParameters securityParameters) : base(securityParameters) { if (securityParameters.ServerCertificateValidationCallback != null) { _certificateValidationCallback = securityParameters.ServerCertificateValidationCallback; } else { _certificateValidationCallback = new ServerCertificateValidationCallback(DefaultCertificateValidationCallback); } if (securityParameters.ClientCertificateSelectionCallback != null) { _certificateSelectionCallback = securityParameters.ClientCertificateSelectionCallback; } else { _certificateSelectionCallback = new ClientCertificateSelectionCallback(DefaultCertificateSelectionCallback); } var clientHello = new HandshakeClientHello(_maxVersion); // add ciphersuites clientHello.CipherSuites.AddRange(_supportedCipherSuites.Select(cs => (CipherSuiteId)cs)); // add compressions clientHello.CompressionMethods.AddRange(_supportedCompressions); // add supported elliptic curves clientHello.Extensions.Add( new HelloEccExtension( new[] { EccNamedCurve.Secp256R1, EccNamedCurve.Secp384R1, EccNamedCurve.BrainpoolP256R1, EccNamedCurve.BrainpoolP384R1, EccNamedCurve.BrainpoolP512R1 })); // add elyptic curves point format clientHello.Extensions.Add( new HelloEccPointFormatsExtension(EccPointFormats.Uncompressed)); // add signature and hash algorithms clientHello.Extensions.Add( new HelloSignatureAlgorithmsExtension( new[] { new SignatureAndHashAlgorithm() { HashAlgorithm = HashAlgorithmType.Sha256, SignatureAlgorithm = SignatureAlgorithmType.Ecdsa }, new SignatureAndHashAlgorithm() { HashAlgorithm = HashAlgorithmType.Sha384, SignatureAlgorithm = SignatureAlgorithmType.Ecdsa }, new SignatureAndHashAlgorithm() { HashAlgorithm = HashAlgorithmType.Sha512, SignatureAlgorithm = SignatureAlgorithmType.Ecdsa }, })); this.logger?.Debug($"Creating ClientHello with max version {_maxVersion}, " + $"supported cipher suites {string.Join(",", _supportedCipherSuites?.Select(cs => $"{cs}"))}, " + $"compression methods {string.Join(",", _supportedCompressions?.Select(c => $"{c}"))}, " + $"extension {string.Join(",", clientHello.Extensions?.Select(ex => ex))} "); this.OutputMessage(clientHello); _connectionState.ClientRandom = clientHello.Random.GetBytes(); }