Beispiel #1
0
        public static void AddCrlForCertificate(
            X509Certificate2 cert,
            SafeX509StoreHandle store,
            X509RevocationMode revocationMode,
            DateTime verificationTime,
            ref TimeSpan remainingDownloadTime)
        {
            // In Offline mode, accept any cached CRL we have.
            // "CRL is Expired" is a better match for Offline than "Could not find CRL"
            if (revocationMode != X509RevocationMode.Online)
            {
                verificationTime = DateTime.MinValue;
            }

            if (AddCachedCrl(cert, store, verificationTime))
            {
                return;
            }

            // Don't do any work if we're over limit or prohibited from fetching new CRLs
            if (remainingDownloadTime <= TimeSpan.Zero ||
                revocationMode != X509RevocationMode.Online)
            {
                return;
            }

            DownloadAndAddCrl(cert, store, ref remainingDownloadTime);
        }
Beispiel #2
0
        private static bool AddCachedCrl(X509Certificate2 cert, SafeX509StoreHandle store, DateTime verificationTime)
        {
            string crlFile = GetCachedCrlPath(cert);

            using (SafeBioHandle bio = Interop.libcrypto.BIO_new_file(crlFile, "rb"))
            {
                if (bio.IsInvalid)
                {
                    return false;
                }

                // X509_STORE_add_crl will increase the refcount on the CRL object, so we should still
                // dispose our copy.
                using (SafeX509CrlHandle crl = Interop.libcrypto.PEM_read_bio_X509_CRL(bio))
                {
                    if (crl.IsInvalid)
                    {
                        return false;
                    }

                    // If crl.LastUpdate is in the past, downloading a new version isn't really going
                    // to help, since we can't rewind the Internet. So this is just going to fail, but
                    // at least it can fail without using the network.
                    //
                    // If crl.NextUpdate is in the past, try downloading a newer version.
                    DateTime nextUpdate = OpenSslX509CertificateReader.ExtractValidityDateTime(
                        Interop.Crypto.GetX509CrlNextUpdate(crl));

                    // OpenSSL is going to convert our input time to universal, so we should be in Local or
                    // Unspecified (local-assumed).
                    Debug.Assert(
                        verificationTime.Kind != DateTimeKind.Utc,
                        "UTC verificationTime should have been normalized to Local");

                    // In the event that we're to-the-second accurate on the match, OpenSSL will consider this
                    // to be already expired.
                    if (nextUpdate <= verificationTime)
                    {
                        return false;
                    }

                    // TODO (#3063): Check the return value of X509_STORE_add_crl, and throw on any error other
                    // than X509_R_CERT_ALREADY_IN_HASH_TABLE
                    Interop.libcrypto.X509_STORE_add_crl(store, crl);

                    return true;
                }
            }
        }
Beispiel #3
0
        private static void DownloadAndAddCrl(
            X509Certificate2 cert,
            SafeX509StoreHandle store,
            ref TimeSpan remainingDownloadTime)
        {
            string url = GetCdpUrl(cert);

            if (url == null)
            {
                return;
            }

            // X509_STORE_add_crl will increase the refcount on the CRL object, so we should still
            // dispose our copy.
            using (SafeX509CrlHandle crl = CertificateAssetDownloader.DownloadCrl(url, ref remainingDownloadTime))
            {
                // null is a valid return (e.g. no remainingDownloadTime)
                if (crl != null && !crl.IsInvalid)
                {
                    // TODO (#3063): Check the return value of X509_STORE_add_crl, and throw on any error other
                    // than X509_R_CERT_ALREADY_IN_HASH_TABLE
                    Interop.libcrypto.X509_STORE_add_crl(store, crl);

                    // Saving the CRL to the disk is just a performance optimization for later requests to not
                    // need to use the network again, so failure to save shouldn't throw an exception or mark
                    // the chain as invalid.
                    try
                    {
                        string crlFile = GetCachedCrlPath(cert, mkDir: true);

                        using (SafeBioHandle bio = Interop.libcrypto.BIO_new_file(crlFile, "wb"))
                        {
                            if (!bio.IsInvalid)
                            {
                                Interop.libcrypto.PEM_write_bio_X509_CRL(bio, crl);
                            }
                        }
                    }
                    catch (IOException)
                    {
                    }
                }
            }
        }
Beispiel #4
0
 internal static extern bool X509StoreAddCert(SafeX509StoreHandle ctx, SafeX509Handle x);
Beispiel #5
0
 internal static extern bool X509StoreSetRevocationFlag(SafeX509StoreHandle ctx, X509RevocationFlag revocationFlag);
Beispiel #6
0
 internal static extern bool X509StoreCtxInit(SafeX509StoreCtxHandle ctx, SafeX509StoreHandle store, SafeX509Handle x509);
Beispiel #7
0
 internal static extern bool X509StoreAddCrl(SafeX509StoreHandle ctx, SafeX509CrlHandle x);
Beispiel #8
0
 internal static extern bool X509_STORE_CTX_init(SafeX509StoreCtxHandle ctx, SafeX509StoreHandle store, SafeX509Handle x509, IntPtr zero);
Beispiel #9
0
 internal static extern bool X509_STORE_add_cert(SafeX509StoreHandle ctx, SafeX509Handle x);
Beispiel #10
0
 internal static extern bool X509_STORE_set_flags(SafeX509StoreHandle ctx, X509VerifyFlags flags);
Beispiel #11
0
 internal static extern bool X509_STORE_add_crl(SafeX509StoreHandle ctx, SafeX509CrlHandle x);