Esempio n. 1
0
        internal SslEngine(
            Communicator communicator,
            X509Certificate2Collection?certificates,
            X509Certificate2Collection?caCertificates,
            LocalCertificateSelectionCallback?certificateSelectionCallback,
            RemoteCertificateValidationCallback?certificateValidationCallback,
            IPasswordCallback?passwordCallback)
        {
            _logger            = communicator.Logger;
            SecurityTraceLevel = communicator.GetPropertyAsInt("IceSSL.Trace.Security") ?? 0;
            _trustManager      = new SslTrustManager(communicator);

            CertificateSelectionCallback        = certificateSelectionCallback;
            RemoteCertificateValidationCallback = certificateValidationCallback;
            PasswordCallback = passwordCallback;

            Certs   = certificates;
            CaCerts = caCertificates;

            // Check for a default directory. We look in this directory for files mentioned in the configuration.
            _defaultDir = communicator.GetProperty("IceSSL.DefaultDir") ?? "";

            string?certStoreLocation = communicator.GetProperty("IceSSL.CertStoreLocation");

            if (certStoreLocation != null && CertificateSelectionCallback != null)
            {
                throw new InvalidConfigurationException(
                          "the property `IceSSL.CertStoreLocation' is incompatible with the certificate selection callback");
            }
            certStoreLocation ??= "CurrentUser";
            StoreLocation storeLocation;

            if (certStoreLocation == "CurrentUser")
            {
                storeLocation = StoreLocation.CurrentUser;
            }
            else if (certStoreLocation == "LocalMachine")
            {
                storeLocation = StoreLocation.LocalMachine;
            }
            else
            {
                _logger.Warning($"Invalid IceSSL.CertStoreLocation value `{certStoreLocation}' adjusted to `CurrentUser'");
                storeLocation = StoreLocation.CurrentUser;
            }
            UseMachineContext = certStoreLocation == "LocalMachine";

            // Protocols selects which protocols to enable
            SslProtocols = ParseProtocols(communicator.GetPropertyAsList("IceSSL.Protocols"));

            // VerifyDepthMax establishes the maximum length of a peer's certificate chain, including the peer's
            // certificate. A value of 0 means there is no maximum.
            int?verifyDepthMax = communicator.GetPropertyAsInt("IceSSL.VerifyDepthMax");

            if (verifyDepthMax != null && RemoteCertificateValidationCallback != null)
            {
                throw new InvalidConfigurationException(
                          "the property `IceSSL.VerifyDepthMax' check is incompatible with the custom remote certificate validation callback");
            }
            _verifyDepthMax = verifyDepthMax ?? 3;

            // CheckCRL determines whether the certificate revocation list is checked, and how strictly.
            CheckCRL = communicator.GetPropertyAsInt("IceSSL.CheckCRL") ?? 0;

            // If the user hasn't supplied a certificate collection, we need to examine the property settings.
            if (Certs == null)
            {
                // If IceSSL.CertFile is defined, load a certificate from a file and add it to the collection.
                // TODO: tracing?
                string?certFile = communicator.GetProperty("IceSSL.CertFile");
                if (certFile != null && CertificateSelectionCallback != null)
                {
                    throw new InvalidConfigurationException(
                              "the property `IceSSL.CertFile' is incompatible with the certificate selection callback");
                }

                string?passwordStr = communicator.GetProperty("IceSSL.Password");
                if (passwordStr != null && CertificateSelectionCallback != null)
                {
                    throw new InvalidConfigurationException(
                              "the property `IceSSL.Password' is incompatible with the certificate selection callback");
                }

                string?findCert = communicator.GetProperty("IceSSL.FindCert");
                if (findCert != null && CertificateSelectionCallback != null)
                {
                    throw new InvalidConfigurationException(
                              "the property `IceSSL.FindCert' is incompatible with the certificate selection callback");
                }
                Certs = new X509Certificate2Collection();
                const string findPrefix = "IceSSL.FindCert.";
                Dictionary <string, string> findCertProps = communicator.GetProperties(forPrefix: findPrefix);

                if (certFile != null)
                {
                    if (!CheckPath(ref certFile))
                    {
                        throw new FileNotFoundException($"certificate file not found: `{certFile}'", certFile);
                    }

                    SecureString?password = null;
                    if (passwordStr != null)
                    {
                        password = CreateSecureString(passwordStr);
                    }
                    else if (PasswordCallback != null)
                    {
                        password = PasswordCallback(certFile);
                    }

                    try
                    {
                        X509Certificate2    cert;
                        X509KeyStorageFlags importFlags;
                        if (UseMachineContext)
                        {
                            importFlags = X509KeyStorageFlags.MachineKeySet;
                        }
                        else
                        {
                            importFlags = X509KeyStorageFlags.UserKeySet;
                        }

                        if (password != null)
                        {
                            cert = new X509Certificate2(certFile, password, importFlags);
                        }
                        else
                        {
                            cert = new X509Certificate2(certFile, "", importFlags);
                        }
                        Certs.Add(cert);
                    }
                    catch (CryptographicException ex)
                    {
                        throw new InvalidConfigurationException(
                                  $"error while attempting to load certificate from `{certFile}'", ex);
                    }
                }
                else if (findCert != null)
                {
                    string certStore = communicator.GetProperty("IceSSL.CertStore") ?? "My";
                    Certs.AddRange(FindCertificates("IceSSL.FindCert", storeLocation, certStore, findCert));
                    if (Certs.Count == 0)
                    {
                        throw new InvalidConfigurationException("no certificates found");
                    }
                }
            }

            if (CaCerts == null)
            {
                string?certAuthFile = communicator.GetProperty("IceSSL.CAs");
                if (certAuthFile != null && RemoteCertificateValidationCallback != null)
                {
                    throw new InvalidConfigurationException(
                              "the property `IceSSL.CAs' is incompatible with the custom remote certificate validation callback");
                }

                bool?usePlatformCAs = communicator.GetPropertyAsBool("IceSSL.UsePlatformCAs");
                if (usePlatformCAs != null && RemoteCertificateValidationCallback != null)
                {
                    throw new InvalidConfigurationException(
                              "the property `IceSSL.UsePlatformCAs' is incompatible with the custom remote certificate validation callback");
                }

                if (RemoteCertificateValidationCallback == null)
                {
                    if (certAuthFile != null || !(usePlatformCAs ?? false))
                    {
                        CaCerts = new X509Certificate2Collection();
                    }

                    if (certAuthFile != null)
                    {
                        if (!CheckPath(ref certAuthFile))
                        {
                            throw new FileNotFoundException("CA certificate file not found: `{certAuthFile}'",
                                                            certAuthFile);
                        }

                        try
                        {
                            using FileStream fs = File.OpenRead(certAuthFile);
                            byte[] data = new byte[fs.Length];
                            fs.Read(data, 0, data.Length);

                            string strbuf = "";
                            try
                            {
                                strbuf = System.Text.Encoding.UTF8.GetString(data);
                            }
                            catch (Exception)
                            {
                                // Ignore
                            }

                            if (strbuf.Length == data.Length)
                            {
                                int  size, startpos, endpos = 0;
                                bool first = true;
                                while (true)
                                {
                                    startpos = strbuf.IndexOf("-----BEGIN CERTIFICATE-----", endpos);
                                    if (startpos != -1)
                                    {
                                        endpos = strbuf.IndexOf("-----END CERTIFICATE-----", startpos);
                                        size   = endpos - startpos + "-----END CERTIFICATE-----".Length;
                                    }
                                    else if (first)
                                    {
                                        startpos = 0;
                                        endpos   = strbuf.Length;
                                        size     = strbuf.Length;
                                    }
                                    else
                                    {
                                        break;
                                    }

                                    byte[] cert = new byte[size];
                                    Buffer.BlockCopy(data, startpos, cert, 0, size);
                                    CaCerts !.Import(cert);
                                    first = false;
                                }
                            }
                            else
                            {
                                CaCerts !.Import(data);
                            }
                        }
                        catch (Exception ex)
                        {
                            throw new InvalidConfigurationException(
                                      $"error while attempting to load CA certificate from {certAuthFile}", ex);
                        }
                    }
                }
            }
        }
Esempio n. 2
0
        internal SslEngine(
            Communicator communicator,
            TlsClientOptions?tlsClientOptions,
            TlsServerOptions?tlsServerOptions)
        {
            _logger            = communicator.Logger;
            SecurityTraceLevel = communicator.GetPropertyAsInt("IceSSL.Trace.Security") ?? 0;
            SslTrustManager    = new SslTrustManager(communicator);

            TlsClientOptions = new TlsClientOptions();
            TlsServerOptions = new TlsServerOptions();

            TlsClientOptions.EnabledSslProtocols = tlsClientOptions?.EnabledSslProtocols ??
                                                   ParseProtocols(communicator.GetPropertyAsList("IceSSL.Protocols"));
            TlsServerOptions.EnabledSslProtocols = tlsServerOptions?.EnabledSslProtocols ??
                                                   ParseProtocols(communicator.GetPropertyAsList("IceSSL.Protocols"));

            TlsServerOptions.RequireClientCertificate = tlsServerOptions?.RequireClientCertificate ?? true;

            // Check for a default directory. We look in this directory for files mentioned in the configuration.
            string defaultDir = communicator.GetProperty("IceSSL.DefaultDir") ?? "";
            X509Certificate2Collection?certificates = null;

            // If IceSSL.CertFile is defined, load a certificate from a file and add it to the collection.
            if (communicator.GetProperty("IceSSL.CertFile") is string certificateFile)
            {
                if (!CheckPath(defaultDir, ref certificateFile))
                {
                    throw new FileNotFoundException(
                              $"certificate file not found: `{certificateFile}'", certificateFile);
                }

                certificates = new X509Certificate2Collection();
                try
                {
                    X509KeyStorageFlags importFlags;
                    if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
                    {
                        importFlags = X509KeyStorageFlags.EphemeralKeySet;
                    }
                    else
                    {
                        importFlags = tlsClientOptions?.UseMachineContex ??
                                      tlsServerOptions?.UseMachineContex ?? false ?
                                      X509KeyStorageFlags.MachineKeySet : X509KeyStorageFlags.UserKeySet;
                    }

                    certificates.Add(communicator.GetProperty("IceSSL.Password") is string password ?
                                     new X509Certificate2(certificateFile, password, importFlags) :
                                     new X509Certificate2(certificateFile, "", importFlags));
                }
                catch (CryptographicException ex)
                {
                    throw new InvalidConfigurationException(
                              $"error while attempting to load certificate from `{certificateFile}'", ex);
                }
            }

            TlsClientOptions.ClientCertificates = tlsClientOptions?.ClientCertificates ?? certificates;
            TlsServerOptions.ServerCertificate  = tlsServerOptions?.ServerCertificate ?? certificates?[0];

            TlsClientOptions.ClientCertificateSelectionCallback = tlsClientOptions?.ClientCertificateSelectionCallback;

            X509Certificate2Collection?caCertificates = null;

            if (communicator.GetProperty("IceSSL.CAs") is string certAuthFile)
            {
                if (!CheckPath(defaultDir, ref certAuthFile))
                {
                    throw new FileNotFoundException($"CA certificate file not found: `{certAuthFile}'", certAuthFile);
                }

                try
                {
                    using FileStream fs = File.OpenRead(certAuthFile);
                    byte[] data = new byte[fs.Length];
                    fs.Read(data, 0, data.Length);

                    string strbuf = "";
                    try
                    {
                        strbuf = System.Text.Encoding.UTF8.GetString(data);
                    }
                    catch (Exception)
                    {
                        // Ignore
                    }

                    string beginCertificateMark = "-----BEGIN CERTIFICATE-----";
                    string endCertificateMark   = "-----END CERTIFICATE-----";

                    caCertificates = new X509Certificate2Collection();
                    if (strbuf.Length == data.Length)
                    {
                        int  size, startpos, endpos = 0;
                        bool first = true;
                        while (true)
                        {
                            startpos = strbuf.IndexOf(beginCertificateMark, endpos);
                            if (startpos != -1)
                            {
                                endpos = strbuf.IndexOf(endCertificateMark, startpos);
                                if (endpos == -1)
                                {
                                    throw new FormatException(
                                              $"end certificate mark `{endCertificateMark}' not found");
                                }
                                size = endpos - startpos + endCertificateMark.Length;
                            }
                            else if (first)
                            {
                                startpos = 0;
                                endpos   = strbuf.Length;
                                size     = strbuf.Length;
                            }
                            else
                            {
                                break;
                            }

                            byte[] cert = new byte[size];
                            Buffer.BlockCopy(data, startpos, cert, 0, size);
                            caCertificates.Import(cert);
                            first = false;
                        }
                    }
                    else
                    {
                        caCertificates.Import(data);
                    }
                }
                catch (Exception ex)
                {
                    throw new InvalidConfigurationException(
                              $"error while attempting to load CA certificate from `{certAuthFile}'", ex);
                }
            }

            if (tlsClientOptions?.ServerCertificateValidationCallback == null)
            {
                TlsClientOptions.ServerCertificateCertificateAuthorities =
                    tlsClientOptions?.ServerCertificateCertificateAuthorities ?? caCertificates;
            }
            else
            {
                TlsClientOptions.ServerCertificateValidationCallback =
                    tlsClientOptions.ServerCertificateValidationCallback;
            }

            if (tlsServerOptions?.ClientCertificateValidationCallback == null)
            {
                TlsServerOptions.ClientCertificateCertificateAuthorities =
                    tlsServerOptions?.ClientCertificateCertificateAuthorities ?? caCertificates;
            }
            else
            {
                TlsServerOptions.ClientCertificateValidationCallback =
                    tlsServerOptions.ClientCertificateValidationCallback;
            }
        }