Beispiel #1
0
        private static void LoadMachineStores()
        {
            Debug.Assert(
                Monitor.IsEntered(s_machineLoadLock),
                "LoadMachineStores assumes a lock(s_machineLoadLock)");

            var rootStore     = new List <X509Certificate2>();
            var intermedStore = new List <X509Certificate2>();

            DirectoryInfo          rootStorePath = null;
            IEnumerable <FileInfo> trustedCertFiles;

            try
            {
                rootStorePath = new DirectoryInfo(Interop.Crypto.GetX509RootStorePath());
            }
            catch (ArgumentException)
            {
                // If SSL_CERT_DIR is set to the empty string, or anything else which gives
                // "The path is not of a legal form", then the GetX509RootStorePath value is ignored.
            }

            if (rootStorePath != null && rootStorePath.Exists)
            {
                trustedCertFiles = rootStorePath.EnumerateFiles();
            }
            else
            {
                trustedCertFiles = Array.Empty <FileInfo>();
            }

            FileInfo rootStoreFile = null;

            try
            {
                rootStoreFile = new FileInfo(Interop.Crypto.GetX509RootStoreFile());
            }
            catch (ArgumentException)
            {
                // If SSL_CERT_FILE is set to the empty string, or anything else which gives
                // "The path is not of a legal form", then the GetX509RootStoreFile value is ignored.
            }

            if (rootStoreFile != null && rootStoreFile.Exists)
            {
                trustedCertFiles = Append(trustedCertFiles, rootStoreFile);
            }

            HashSet <X509Certificate2> uniqueRootCerts         = new HashSet <X509Certificate2>();
            HashSet <X509Certificate2> uniqueIntermediateCerts = new HashSet <X509Certificate2>();

            foreach (FileInfo file in trustedCertFiles)
            {
                using (SafeBioHandle fileBio = Interop.Crypto.BioNewFile(file.FullName, "rb"))
                {
                    ICertificatePal pal;

                    while (CertificatePal.TryReadX509Pem(fileBio, out pal) ||
                           CertificatePal.TryReadX509Der(fileBio, out pal))
                    {
                        X509Certificate2 cert = new X509Certificate2(pal);

                        // The HashSets are just used for uniqueness filters, they do not survive this method.
                        if (StringComparer.Ordinal.Equals(cert.Subject, cert.Issuer))
                        {
                            if (uniqueRootCerts.Add(cert))
                            {
                                rootStore.Add(cert);
                                continue;
                            }
                        }
                        else
                        {
                            if (uniqueIntermediateCerts.Add(cert))
                            {
                                intermedStore.Add(cert);
                                continue;
                            }
                        }

                        // There's a good chance we'll encounter duplicates on systems that have both one-cert-per-file
                        // and one-big-file trusted certificate stores. Anything that wasn't unique will end up here.
                        cert.Dispose();
                    }
                }
            }

            var rootStorePal = new CollectionBackedStoreProvider(rootStore);

            s_machineIntermediateStore = new CollectionBackedStoreProvider(intermedStore);

            // s_machineRootStore's nullarity is the loaded-state sentinel, so write it with Volatile.
            Debug.Assert(Monitor.IsEntered(s_machineLoadLock), "LoadMachineStores assumes a lock(s_machineLoadLock)");
            Volatile.Write(ref s_machineRootStore, rootStorePal);
        }
Beispiel #2
0
        private static void LoadMachineStores()
        {
            Debug.Assert(
                Monitor.IsEntered(s_machineLoadLock),
                "LoadMachineStores assumes a lock(s_machineLoadLock)");

            var rootStore     = new List <X509Certificate2>();
            var intermedStore = new List <X509Certificate2>();

            DirectoryInfo          rootStorePath = null;
            IEnumerable <FileInfo> trustedCertFiles;

            try
            {
                rootStorePath = new DirectoryInfo(Interop.Crypto.GetX509RootStorePath());
            }
            catch (ArgumentException)
            {
                // If SSL_CERT_DIR is set to the empty string, or anything else which gives
                // "The path is not of a legal form", then the GetX509RootStorePath value is ignored.
            }

            if (rootStorePath != null && rootStorePath.Exists)
            {
                trustedCertFiles = rootStorePath.EnumerateFiles();
            }
            else
            {
                trustedCertFiles = Array.Empty <FileInfo>();
            }

            FileInfo rootStoreFile = null;

            try
            {
                rootStoreFile = new FileInfo(Interop.Crypto.GetX509RootStoreFile());
            }
            catch (ArgumentException)
            {
                // If SSL_CERT_FILE is set to the empty string, or anything else which gives
                // "The path is not of a legal form", then the GetX509RootStoreFile value is ignored.
            }

            if (rootStoreFile != null && rootStoreFile.Exists)
            {
                trustedCertFiles = trustedCertFiles.Prepend(rootStoreFile);
            }

            HashSet <X509Certificate2> uniqueRootCerts         = new HashSet <X509Certificate2>();
            HashSet <X509Certificate2> uniqueIntermediateCerts = new HashSet <X509Certificate2>();

            foreach (FileInfo file in trustedCertFiles)
            {
                using (SafeBioHandle fileBio = Interop.Crypto.BioNewFile(file.FullName, "rb"))
                {
                    // The handle may be invalid, for example when we don't have read permission for the file.
                    if (fileBio.IsInvalid)
                    {
                        Interop.Crypto.ErrClearError();
                        continue;
                    }

                    ICertificatePal pal;

                    // Some distros ship with two variants of the same certificate.
                    // One is the regular format ('BEGIN CERTIFICATE') and the other
                    // contains additional AUX-data ('BEGIN TRUSTED CERTIFICATE').
                    // The additional data contains the appropriate usage (e.g. emailProtection, serverAuth, ...).
                    // Because corefx doesn't validate for a specific usage, derived certificates are rejected.
                    // For now, we skip the certificates with AUX data and use the regular certificates.
                    while (OpenSslX509CertificateReader.TryReadX509PemNoAux(fileBio, out pal) ||
                           OpenSslX509CertificateReader.TryReadX509Der(fileBio, out pal))
                    {
                        X509Certificate2 cert = new X509Certificate2(pal);

                        // The HashSets are just used for uniqueness filters, they do not survive this method.
                        if (StringComparer.Ordinal.Equals(cert.Subject, cert.Issuer))
                        {
                            if (uniqueRootCerts.Add(cert))
                            {
                                rootStore.Add(cert);
                                continue;
                            }
                        }
                        else
                        {
                            if (uniqueIntermediateCerts.Add(cert))
                            {
                                intermedStore.Add(cert);
                                continue;
                            }
                        }

                        // There's a good chance we'll encounter duplicates on systems that have both one-cert-per-file
                        // and one-big-file trusted certificate stores. Anything that wasn't unique will end up here.
                        cert.Dispose();
                    }
                }
            }

            var rootStorePal = new CollectionBackedStoreProvider(rootStore);

            s_machineIntermediateStore = new CollectionBackedStoreProvider(intermedStore);

            // s_machineRootStore's nullarity is the loaded-state sentinel, so write it with Volatile.
            Debug.Assert(Monitor.IsEntered(s_machineLoadLock), "LoadMachineStores assumes a lock(s_machineLoadLock)");
            Volatile.Write(ref s_machineRootStore, rootStorePal);
        }