예제 #1
0
파일: SslSocket.cs 프로젝트: mreinart/ice
        public override async ValueTask InitializeAsync(CancellationToken cancel)
        {
            await _underlying.InitializeAsync(cancel).ConfigureAwait(false);

            // This can only be created with a connected socket.
            _sslStream = new SslStream(new NetworkStream(_underlying.Socket !, false), false);

            try
            {
                if (_incoming)
                {
                    var options = new SslServerAuthenticationOptions();
                    options.ServerCertificate                   = _engine.TlsServerOptions.ServerCertificate;
                    options.ClientCertificateRequired           = _engine.TlsServerOptions.RequireClientCertificate;
                    options.EnabledSslProtocols                 = _engine.TlsServerOptions.EnabledSslProtocols !.Value;
                    options.RemoteCertificateValidationCallback =
                        _engine.TlsServerOptions.ClientCertificateValidationCallback ??
                        RemoteCertificateValidationCallback;
                    options.CertificateRevocationCheckMode = X509RevocationMode.NoCheck;
                    await _sslStream.AuthenticateAsServerAsync(options, cancel).ConfigureAwait(false);
                }
                else
                {
                    var options = new SslClientAuthenticationOptions();
                    options.TargetHost          = _host;
                    options.ClientCertificates  = _engine.TlsClientOptions.ClientCertificates;
                    options.EnabledSslProtocols = _engine.TlsClientOptions.EnabledSslProtocols !.Value;
                    options.RemoteCertificateValidationCallback =
                        _engine.TlsClientOptions.ServerCertificateValidationCallback ??
                        RemoteCertificateValidationCallback;
                    options.LocalCertificateSelectionCallback =
                        _engine.TlsClientOptions.ClientCertificateSelectionCallback ??
                        (options.ClientCertificates?.Count > 0 ?
                         CertificateSelectionCallback : (LocalCertificateSelectionCallback?)null);
                    options.CertificateRevocationCheckMode = X509RevocationMode.NoCheck;
                    await _sslStream.AuthenticateAsClientAsync(options, cancel).ConfigureAwait(false);
                }
            }
            catch (IOException ex) when(ex.IsConnectionLost())
            {
                throw new ConnectionLostException(ex, RetryPolicy.AfterDelay(TimeSpan.Zero));
            }
            catch (IOException ex)
            {
                throw new TransportException(ex, RetryPolicy.AfterDelay(TimeSpan.Zero));
            }
            catch (AuthenticationException ex)
            {
                throw new TransportException(ex, RetryPolicy.OtherReplica);
            }

            if (_engine.SecurityTraceLevel >= 1)
            {
                _engine.TraceStream(_sslStream, ToString());
            }

            // Use a buffered stream for writes. This ensures that small requests which are composed of multiple
            // small buffers will be sent within a single SSL frame.
            _writeStream = new BufferedStream(_sslStream);
        }
예제 #2
0
        public async ValueTask InitializeAsync(CancellationToken cancel)
        {
            await _underlying.InitializeAsync(cancel).ConfigureAwait(false);

            SslStream = new SslStream(new NetworkStream(_underlying.Socket !, false), false);

            try
            {
                if (_incoming)
                {
                    var options = new SslServerAuthenticationOptions();
                    options.ServerCertificate                   = _engine.TlsServerOptions.ServerCertificate;
                    options.ClientCertificateRequired           = _engine.TlsServerOptions.RequireClientCertificate;
                    options.EnabledSslProtocols                 = _engine.TlsServerOptions.EnabledSslProtocols !.Value;
                    options.RemoteCertificateValidationCallback =
                        _engine.TlsServerOptions.ClientCertificateValidationCallback ??
                        RemoteCertificateValidationCallback;
                    options.CertificateRevocationCheckMode = X509RevocationMode.NoCheck;
                    await SslStream.AuthenticateAsServerAsync(options, cancel).ConfigureAwait(false);
                }
                else
                {
                    var options = new SslClientAuthenticationOptions();
                    options.TargetHost          = _host;
                    options.ClientCertificates  = _engine.TlsClientOptions.ClientCertificates;
                    options.EnabledSslProtocols = _engine.TlsClientOptions.EnabledSslProtocols !.Value;
                    options.RemoteCertificateValidationCallback =
                        _engine.TlsClientOptions.ServerCertificateValidationCallback ??
                        RemoteCertificateValidationCallback;
                    options.LocalCertificateSelectionCallback =
                        _engine.TlsClientOptions.ClientCertificateSelectionCallback ??
                        (options.ClientCertificates?.Count > 0 ? CertificateSelectionCallback : (LocalCertificateSelectionCallback?)null);
                    options.CertificateRevocationCheckMode = X509RevocationMode.NoCheck;
                    await SslStream.AuthenticateAsClientAsync(options, cancel).ConfigureAwait(false);
                }
            }
            catch (IOException ex) when(ex.IsConnectionLost())
            {
                throw new ConnectionLostException(ex);
            }
            catch (IOException ex)
            {
                throw new TransportException(ex);
            }
            catch (AuthenticationException ex)
            {
                throw new TransportException(ex);
            }

            string description = ToString();

            if (!_engine.SslTrustManager.Verify(_incoming,
                                                SslStream.RemoteCertificate as X509Certificate2,
                                                _adapterName ?? "",
                                                description))
            {
                var s = new StringBuilder();
                s.Append(_incoming ? "incoming " : "outgoing");
                s.Append("connection rejected by trust manager\n");
                s.Append(description);
                if (_engine.SecurityTraceLevel >= 1)
                {
                    _communicator.Logger.Trace(_engine.SecurityTraceCategory, s.ToString());
                }

                throw new TransportException(s.ToString());
            }

            if (_engine.SecurityTraceLevel >= 1)
            {
                _engine.TraceStream(SslStream, description);
            }

            // Use a buffered stream for writes. This ensures that small requests which are composed of multiple
            // small buffers will be sent within a single SSL frame.
            _writeStream = new BufferedStream(SslStream);
        }
예제 #3
0
        public int Initialize(ref ArraySegment <byte> readBuffer, IList <ArraySegment <byte> > writeBuffer)
        {
            if (!_isConnected)
            {
                int status = _delegate.Initialize(ref readBuffer, writeBuffer);
                if (status != SocketOperation.None)
                {
                    return(status);
                }
                _isConnected = true;
            }

            Socket?fd = _delegate.Fd();

            Debug.Assert(fd != null);

            Network.SetBlock(fd, true); // SSL requires a blocking socket

            //
            // For timeouts to work properly, we need to receive/send
            // the data in several chunks. Otherwise, we would only be
            // notified when all the data is received/written. The
            // connection timeout could easily be triggered when
            // receiving/sending large frames.
            //
            _maxSendPacketSize = Math.Max(512, Network.GetSendBufferSize(fd));
            _maxRecvPacketSize = Math.Max(512, Network.GetRecvBufferSize(fd));

            if (SslStream == null)
            {
                try
                {
                    SslStream = new SslStream(
                        new NetworkStream(fd, false),
                        false,
                        _engine.RemoteCertificateValidationCallback ?? RemoteCertificateValidationCallback,
                        _engine.CertificateSelectionCallback ?? CertificateSelectionCallback);
                }
                catch (IOException ex)
                {
                    if (Network.ConnectionLost(ex))
                    {
                        throw new ConnectionLostException(ex);
                    }
                    else
                    {
                        throw new TransportException(ex);
                    }
                }
                return(SocketOperation.Connect);
            }

            Debug.Assert(SslStream.IsAuthenticated);
            _authenticated = true;

            string description = ToString();

            if (!_engine.TrustManager.Verify(_incoming,
                                             SslStream.RemoteCertificate as X509Certificate2,
                                             _adapterName ?? "",
                                             description))
            {
                string msg = string.Format("{0} connection rejected by trust manager\n{1}",
                                           _incoming ? "incoming" : "outgoing",
                                           description);
                if (_engine.SecurityTraceLevel >= 1)
                {
                    _communicator.Logger.Trace(_engine.SecurityTraceCategory, msg);
                }

                throw new TransportException(msg);
            }

            if (_engine.SecurityTraceLevel >= 1)
            {
                _engine.TraceStream(SslStream, ToString());
            }
            return(SocketOperation.None);
        }