/// <summary> /// Gets the validated stream on client. /// </summary> /// <param name="serverName">Name of the server.</param> /// <param name="client">TCP client</param> /// <param name="timeout">Time to wait for the validation</param> /// <param name="cancellationToken">Token to be observed for cancellation signal</param> /// <returns>A Task that resolves to the validated stream</returns> public virtual async Task <Stream> AuthenticateAsClient(string serverName, TcpClient client, TimeSpan timeout, CancellationToken cancellationToken) { if (client == null) { throw new ArgumentNullException("client"); } Stream clientStream = null; SslStream sslStream = null; try { clientStream = client.GetStream(); sslStream = new SslStream( clientStream, false, this.configuration.RemoteCertificateValidationCallback ?? this.certificateValidator.ValidateServerCertificate, this.configuration.LocalCertificateSelectionCallback); X509CertificateCollection coll = new X509CertificateCollection(this.identities.ClientIdentities); SecureTransportEventSource.Log.AuthenticateAsClient(this.transportId, (int)timeout.TotalMilliseconds, this.configuration.MustCheckCertificateRevocation, this.configuration.MustCheckCertificateTrustChain); Task task = sslStream.AuthenticateAsClientAsync( serverName, coll, this.configuration.SupportedProtocols, this.configuration.MustCheckCertificateRevocation); await Task.WhenAny(task, Task.Delay(timeout, cancellationToken)); if (!task.IsCompleted) { throw SecureTransportException.SslValidationTimedOut(); } // Task is already completed, await it to ensure that it successfully // completed. await task; return(sslStream); } catch (Exception ex) { SecureTransportEventSource.Log.AuthenticateAsClientFailed(this.transportId, ex.ToString()); if (sslStream != null) { sslStream.Dispose(); } else { if (clientStream != null) { clientStream.Dispose(); } } throw; } }
/// <summary> /// Gets the validated stream on server. /// </summary> /// <param name="client">TCP client</param> /// <param name="timeout">Time to wait for the validation</param> /// <param name="cancellationToken">Token to be observed for cancellation signal</param> /// <returns>A Task that resolves to the validated stream</returns> public virtual async Task <Stream> AuthenticateAsServer(TcpClient client, TimeSpan timeout, CancellationToken cancellationToken) { if (client == null) { throw new ArgumentNullException("client"); } SslStream sslStream = null; Stream clientStream = client.GetStream(); try { // We want to use ONLY the first cert in the given list X509Certificate serverCertificate = this.identities.ServerIdentity; if (serverCertificate == null) { throw SecureTransportException.NoServerCertificate(); } SecureTransportEventSource.Log.AuthenticateAsServer(this.transportId, (int)timeout.TotalMilliseconds, this.configuration.MustCheckCertificateRevocation, this.configuration.MustCheckCertificateTrustChain); sslStream = new SslStream( clientStream, false, this.configuration.RemoteCertificateValidationCallback ?? this.certificateValidator.ValidateClientCertificate, this.configuration.LocalCertificateSelectionCallback); Task task = sslStream.AuthenticateAsServerAsync( serverCertificate, clientCertificateRequired: this.configuration.IsClientCertificateRequired, enabledSslProtocols: this.configuration.SupportedProtocols, checkCertificateRevocation: this.configuration.MustCheckCertificateRevocation); await Task.WhenAny(task, Task.Delay(timeout, cancellationToken)); if (!task.IsCompleted) { throw SecureTransportException.SslValidationTimedOut(); } // Task is already completed, await it to ensure that it successfully // completed. await task; return(sslStream); } catch (Exception ex) { SecureTransportEventSource.Log.AuthenticateAsServerFailed(this.transportId, ex.ToString()); if (sslStream != null) { sslStream.Dispose(); } else { clientStream.Dispose(); client.Close(); } throw; } }