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) { if (!Interop.Crypto.X509StoreAddCrl(store, crl)) { // Ignore error "cert already in store", throw on anything else. In any case the error queue will be cleared. if (X509_R_CERT_ALREADY_IN_HASH_TABLE == Interop.Crypto.ErrPeekLastError()) { Interop.Crypto.ErrClearError(); } else { throw Interop.Crypto.CreateOpenSslCryptographicException(); } } // 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.Crypto.BioNewFile(crlFile, "wb")) { if (bio.IsInvalid || Interop.Crypto.PemWriteBioX509Crl(bio, crl) == 0) { // No bio, or write failed Interop.Crypto.ErrClearError(); } } } catch (UnauthorizedAccessException) { } catch (IOException) { } } } }
private static X509Certificate2 DownloadCertificate( byte[] authorityInformationAccess, ref TimeSpan remainingDownloadTime) { // Don't do any work if we're over limit. if (remainingDownloadTime <= TimeSpan.Zero) { return(null); } DerSequenceReader reader = new DerSequenceReader(authorityInformationAccess); while (reader.HasData) { DerSequenceReader innerReader = reader.ReadSequence(); // If the sequence's first element is a sequence, unwrap it. if (innerReader.PeekTag() == ConstructedSequenceTagId) { innerReader = innerReader.ReadSequence(); } Oid oid = innerReader.ReadOid(); if (StringComparer.Ordinal.Equals(oid.Value, Oids.CertificateAuthorityIssuers)) { string uri = innerReader.ReadIA5String(); Uri parsedUri; if (!Uri.TryCreate(uri, UriKind.Absolute, out parsedUri)) { continue; } if (!StringComparer.Ordinal.Equals(parsedUri.Scheme, "http")) { continue; } return(CertificateAssetDownloader.DownloadCertificate(uri, ref remainingDownloadTime)); } } return(null); }
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) { } } } }
private static X509Certificate2 DownloadCertificate( byte[] authorityInformationAccess, ref TimeSpan remainingDownloadTime) { // Don't do any work if we're over limit. if (remainingDownloadTime <= TimeSpan.Zero) { return(null); } string uri = FindHttpAiaRecord(authorityInformationAccess, Oids.CertificateAuthorityIssuers); if (uri == null) { return(null); } return(CertificateAssetDownloader.DownloadCertificate(uri, ref remainingDownloadTime)); }