/// <summary> /// Gets the Thumbprint of the certificate that signed another /// </summary> /// <param name="CertContent">Certificate to check signer of</param> /// <param name="CAContent">List of possible signers</param> /// <returns>Thumbprint of signer, null if not found</returns> public static string GetSignerCertHash(string CertContent, string[] CAContent) { var CAs = CAContent.Select(m => GetCert(m)).ToArray(); var Cert = GetCert(CertContent); if (CAs.All(m => m != null) && Cert != null) { X509Chain chain = new X509Chain(); chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; chain.ChainPolicy.RevocationFlag = X509RevocationFlag.ExcludeRoot; chain.ChainPolicy.VerificationFlags = //Allow our own CA X509VerificationFlags.AllowUnknownCertificateAuthority | //Don't care if one of the certs has expired X509VerificationFlags.IgnoreNotTimeValid | //Don't care if the client cert validity is outside of the root cert X509VerificationFlags.IgnoreNotTimeNested; chain.ChainPolicy.VerificationTime = DateTime.Now; chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 0, 0); chain.ChainPolicy.ExtraStore.AddRange(CAs); if (!chain.Build(Cert)) { string[] errors = chain.ChainStatus .Select(x => string.Format("{0} ({1})", x.StatusInformation.Trim(), x.Status)) .ToArray(); string certificateErrorsString = "Unknown errors."; if (errors != null && errors.Length > 0) { certificateErrorsString = string.Join(", ", errors); } Logger.Error("Unable to construct Certificate Chain. Error: {0}", certificateErrorsString); } else { if (chain.ChainElements.Count > 1) { var T = chain.ChainElements[chain.ChainElements.Count - 1].Certificate.Thumbprint; if (CAs.Any(m => m.Thumbprint == T)) { Logger.Debug("Thumbprint found: {0}", T); chain.Reset(); return(T); } else { Logger.Warn("Chain completed by a CA certificate from the system, not our own"); } } } Logger.Warn("Attempted to find CA but none was available. Maybe it was deleted"); chain.Reset(); } return(null); }
public void Build_Twice_WithReset() { X509Chain c = new X509Chain(); Assert.IsFalse(c.Build(cert1), "Build-1"); c.Reset(); Assert.IsFalse(c.Build(cert2), "Build-2"); c.Reset(); CheckDefaultChain(c); }
private static bool ValidateServerCertificateChain(object sender, X509Certificate pfxFormattedCertificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { if (sslPolicyErrors == SslPolicyErrors.None) { return(true); } System.Console.WriteLine("Certificate error: {0}", sslPolicyErrors); var serverCert = _spineConfiguration.server_ca_certchain; var serverCertData = CertificateHelper.ExtractCertInstances(serverCert); var x509ServerCertificateSubCa = new X509Certificate2(serverCertData[0]); var x509ServerCertificateRootCa = new X509Certificate2(serverCertData[1]); chain.Reset(); chain.ChainPolicy.VerificationFlags = X509VerificationFlags.IgnoreRootRevocationUnknown; chain.ChainPolicy.RevocationMode = X509RevocationMode.Online; chain.ChainPolicy.ExtraStore.Add(x509ServerCertificateSubCa); chain.ChainPolicy.ExtraStore.Add(x509ServerCertificateRootCa); //if (chain.Build(pfxFormattedCertificate)) return true; if (chain.ChainStatus.Where(chainStatus => chainStatus.Status != X509ChainStatusFlags.NoError).All(chainStatus => chainStatus.Status != X509ChainStatusFlags.UntrustedRoot)) { return(false); } var providedRoot = chain.ChainElements[^ 1];
/// <summary> /// Adds key recovery agent (KRA) certificates to the CA. This method do not writes them to a Certification Authority. /// </summary> /// <param name="certs">One or more <see cref="X509Certificate2"/> object to add.</param> /// <exception cref="ArgumentNullException">The <strong>certs</strong> parameter is null or empty array.</exception> /// <remarks> /// If <see cref="Certificate"/> property already contains the certificate passed in <strong>certs</strong> parameter, /// the method skips the certificate. /// </remarks> public void Add(X509Certificate2[] certs) { if (certs == null || certs.Length == 0) { throw new ArgumentNullException(nameof(certs)); } Int32 before = _certs.Count; X509Chain chain = new X509Chain(); chain.ChainPolicy.ApplicationPolicy.Add(new Oid("1.3.6.1.4.1.311.21.6")); foreach (X509Certificate2 cert in certs.Where(chain.Build)) { if ( !String.IsNullOrEmpty(cert.Thumbprint) && Certificate.Find(X509FindType.FindByThumbprint, cert.Thumbprint, false).Count == 0 ) { _certs.Add(cert); } chain.Reset(); } if (_certs.Count > before) { IsModified = true; } }
static CertInfo ToCertInfo(X509Certificate2 cert) { var chain = new X509Chain(); chain.Build(cert); CertInfo certInfo = null; for (int i = chain.ChainElements.Count - 1; i >= 0; i--) { var certElement = chain.ChainElements[i]; certInfo = new CertInfo( certElement.Certificate.FriendlyName, certElement.Certificate.Subject, certElement.Certificate.Thumbprint, certElement.Certificate.SerialNumber, certElement.Certificate.NotBefore, certElement.Certificate.NotAfter, certInfo, certElement.Certificate.Verify(), certElement.ChainElementStatus.Select(x => x.StatusInformation.ToString()).ToArray()); } chain.Reset(); return(certInfo); }
public static void TestResetMethod() { using (var sampleCert = new X509Certificate2(TestData.DssCer)) using (var chainHolder = new ChainHolder()) { X509Chain chain = chainHolder.Chain; chain.ChainPolicy.ExtraStore.Add(sampleCert); bool valid = chain.Build(sampleCert); Assert.False(valid); chainHolder.DisposeChainElements(); chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority; chain.ChainPolicy.VerificationTime = new DateTime(2015, 10, 15, 12, 01, 01, DateTimeKind.Local); chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; valid = chain.Build(sampleCert); Assert.True(valid, "Chain built validly"); Assert.Equal(1, chain.ChainElements.Count); chainHolder.DisposeChainElements(); chain.Reset(); Assert.Equal(0, chain.ChainElements.Count); // ChainPolicy did not reset (for desktop compat) Assert.Equal(X509VerificationFlags.AllowUnknownCertificateAuthority, chain.ChainPolicy.VerificationFlags); valid = chain.Build(sampleCert); Assert.Equal(1, chain.ChainElements.Count); // This succeeds because ChainPolicy did not reset Assert.True(valid, "Chain built validly after reset"); } }
public void Build_Cert1_X509RevocationMode_NoCheck() { X509Chain c = new X509Chain(); c.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; foreach (X509VerificationFlags vf in Enum.GetValues(typeof(X509VerificationFlags))) { c.ChainPolicy.VerificationFlags = vf; CheckCert1(c); c.Reset(); } }
public void Build_Cert2() { X509Chain c = new X509Chain(); foreach (X509VerificationFlags vf in Enum.GetValues(typeof(X509VerificationFlags))) { c.ChainPolicy.VerificationFlags = vf; CheckCert2(c); c.Reset(); } // minimal criteria for success c.ChainPolicy.VerificationFlags = X509VerificationFlags.IgnoreNotTimeValid | X509VerificationFlags.AllowUnknownCertificateAuthority; CheckCert2(c); }
private void Reset () { filename = null; entry = null; hash = null; signedHash = null; signingCertificate = null; reason = -1; trustedRoot = false; trustedTimestampRoot = false; signerChain.Reset (); timestampChain.Reset (); timestamp = DateTime.MinValue; }
public static X509Certificate2[] CompleteChain(this X509Certificate2[] certs) { X509Chain chain = null; try { chain = GetChainFromCerts(certs); chain.Build(certs[0]); return(chain.ChainElements.Cast <X509ChainElement>().Select(x => x.Certificate).ToArray()); } finally { chain?.Reset(); } }
public static (IList <X509Certificate2>, Option <string>) BuildCertificateList(X509Certificate2 cert, Option <IList <X509Certificate2> > additionalCACertificates) { var chain = new X509Chain { ChainPolicy = { // For performance reasons do not check revocation status. RevocationMode = X509RevocationMode.NoCheck, // Does not check revocation status of the root certificate (sounds like it is meaningless with the option above - ask Simon or Alex) RevocationFlag = X509RevocationFlag.ExcludeRoot, // Certificate Authority can be unknown if it is not issued directly by a well-known CA VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority } }; if (additionalCACertificates.HasValue) { foreach (X509Certificate2 additionalCertificate in additionalCACertificates.GetOrElse(new List <X509Certificate2>())) { if (additionalCertificate != null) { chain.ChainPolicy.ExtraStore.Add(additionalCertificate); } } } try { bool chainBuildSucceeded = chain.Build(cert); X509ChainStatusFlags flags = X509ChainStatusFlags.UntrustedRoot | X509ChainStatusFlags.PartialChain; List <X509ChainStatus> filteredStatus = chain.ChainStatus.Where(cs => !flags.HasFlag(cs.Status)).ToList(); if (!chainBuildSucceeded || filteredStatus.Count > 0) { string errors = $"Certificate with subject: {cert.Subject} failed with errors: "; string s = filteredStatus .Select(c => c.StatusInformation) .Aggregate(errors, (prev, curr) => $"{prev} {curr}"); return(new List <X509Certificate2>(), Option.Some(s)); } IList <X509Certificate2> chainElements = GetCertificatesFromChain(chain); return(chainElements, Option.None <string>()); } finally { chain.Reset(); } }
static bool VerifyCrl(X509Crl crl) { X509Certificate issuer = FindCrlIssuer(crl); if (issuer == null) { return(false); } if (!crl.VerifySignature(issuer)) { return(false); } chain.Reset(); return(chain.Build(issuer)); }
private static bool ValidateServerCertificateChain(X509Chain chain, X509Certificate2 x509ServerCertificateSubCa, X509Certificate2 x509ServerCertificateRootCa, X509Certificate2 pfxFormattedCertificate) { chain.Reset(); chain.ChainPolicy.VerificationFlags = X509VerificationFlags.IgnoreRootRevocationUnknown; chain.ChainPolicy.RevocationMode = X509RevocationMode.Online; chain.ChainPolicy.ExtraStore.Add(x509ServerCertificateSubCa); chain.ChainPolicy.ExtraStore.Add(x509ServerCertificateRootCa); if (chain.Build(pfxFormattedCertificate)) { return(true); } if (chain.ChainStatus.Where(chainStatus => chainStatus.Status != X509ChainStatusFlags.NoError).All(chainStatus => chainStatus.Status != X509ChainStatusFlags.UntrustedRoot)) { return(false); } var providedRoot = chain.ChainElements[^ 1];
void buildSignerCertChain() { X509Chain chain = new X509Chain { ChainPolicy = { RevocationMode = X509RevocationMode.NoCheck } }; chain.Build(SignerCertificate); for (Int32 index = 0; index < chain.ChainElements.Count; index++) { X509Certificate2 cert = chain.ChainElements[index].Certificate; if (index > 0 && cert.Subject == cert.Issuer) { break; } _signerChain.Add(cert); } chain.Reset(); }
public static X509Certificate2 GetIssuer(X509Certificate2 leafCert) { if (leafCert.Subject == leafCert.Issuer) { return(leafCert); } X509Chain chain = new X509Chain(); chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; chain.Build(leafCert); X509Certificate2 issuer = null; if (chain.ChainElements.Count > 1) { issuer = chain.ChainElements[1].Certificate; } chain.Reset(); return(issuer); }
/// <summary> /// Validates the client certificate by checking whether it has been signed by the server. /// </summary> /// <param name="sender">The sender of the callback.</param> /// <param name="certificate">The client certificate to validate.</param> /// <param name="chain">The X.509 chain.</param> /// <param name="sslPolicyErrors">The SSL policy errors.</param> /// <returns>Returns <value>true</value> when the validation was successful, otherwise <value>false</value>.</returns> public bool ValidateClientCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { #if DEBUG // for debugging don't validate client certificate return(true); #else // if client does not provide a certificate, don't accept connection if (certificate == null) { return(false); } chain.Reset(); chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority; chain.ChainPolicy.VerificationTime = DateTime.UtcNow; chain.ChainPolicy.ExtraStore.Add(_serverCertificate); chain.Build(new X509Certificate2(certificate)); bool result = true; foreach (var status in chain.ChainStatus) { if (status.Status == X509ChainStatusFlags.UntrustedRoot) { // self-signed certificates with an untrusted root are valid. continue; } else { if (status.Status != X509ChainStatusFlags.NoError) { // if there are any other errors in the certificate chain, the certificate is invalid. result = false; } } } return(result); #endif }
public static bool ValidateChain(this X509Certificate2[] certs) { if ((certs?.Length ?? 0) == 0) { return(false); } // TODO: spravit cache pre validacie; vyprazdnit ak bola menej ako cca 1 minuta X509Chain chain = null; try { chain = GetChainFromCerts(certs); return(chain.Build(certs[0])); } finally { chain?.Reset(); } }
/// <summary> /// Validates the certificate when <see cref="SslStream"/>.AuthenticateAsClient() is called. /// </summary> /// <param name="sender"></param> /// <param name="certificate"></param> /// <param name="chain"></param> /// <param name="sslPolicyErrors"></param> /// <returns>True when the certificate is valid, False when the certificate is invalid.</returns> protected virtual bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { if (_allowUntrustedRootCa) { // remove this line if commercial CAs are not allowed to issue certificate for your service. if ((sslPolicyErrors & SslPolicyErrors.None) > 0) { return(true); } if ((sslPolicyErrors & SslPolicyErrors.RemoteCertificateNameMismatch) > 0 || (sslPolicyErrors & SslPolicyErrors.RemoteCertificateNotAvailable) > 0) { return(false); } // execute certificate chaining engine and ignore only "UntrustedRoot" error X509Chain customChain = new X509Chain { ChainPolicy = { VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority } }; Boolean retValue = customChain.Build(chain.ChainElements[0].Certificate); // RELEASE unmanaged resources behind X509Chain class. customChain.Reset(); return(retValue); } //Full Certificate-Validation if (sslPolicyErrors == SslPolicyErrors.None) { return(true); } Console.WriteLine("Certificate error: {0}", sslPolicyErrors); // Do not allow this client to communicate with unauthenticated servers. return(false); }
public X509Certificate2 GetIssuerCertificate(X509Certificate2 cert) { // Self Signed Certificate if (cert.Subject == cert.Issuer) { return(cert); } var chain = new X509Chain(); chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; chain.Build(cert); X509Certificate2 issuer = null; if (chain.ChainElements.Count > 1) { issuer = chain.ChainElements[1].Certificate; } chain.Reset(); return(issuer); }
public override void Validate(X509Certificate2 cert) { if (check_peer) { X509Store store = new X509Store(); store.Open(OpenFlags.ReadOnly); foreach (X509Certificate2 c in store.Certificates) { if (c.Thumbprint == cert.Thumbprint) { return; } } } if (check_chain) { if (chain == null) { if (use_machine_ctx) { chain = X509Chain.Create(); } else { chain = new X509Chain(); } chain.ChainPolicy = policy; } else { chain.Reset(); } if (chain.Build(cert)) { return; } } throw new ArgumentException("The argument certificate is invalid."); }
Boolean ServerCertificateValidationCallback(Object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { String rootCAThumbprint = ""; // write your code to get your CA's thumbprint // remove this line if commercial CAs are not allowed to issue certificate for your service. if ((sslPolicyErrors & (SslPolicyErrors.None)) > 0) { return(true); } if ( (sslPolicyErrors & (SslPolicyErrors.RemoteCertificateNameMismatch)) > 0 || (sslPolicyErrors & (SslPolicyErrors.RemoteCertificateNotAvailable)) > 0 ) { return(false); } // get last chain element that should contain root CA certificate // but this may not be the case in partial chains X509Certificate2 projectedRootCert = chain.ChainElements[chain.ChainElements.Count - 1].Certificate; if (projectedRootCert.Thumbprint != rootCAThumbprint) { return(false); } // execute certificate chaining engine and ignore only "UntrustedRoot" error X509Chain customChain = new X509Chain { ChainPolicy = { VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority } }; Boolean retValue = customChain.Build(chain.ChainElements[0].Certificate); // RELEASE unmanaged resources behind X509Chain class. chain.Reset(); return(retValue); }
static bool ServerCertificateValidationCallback(X509Certificate2 ourCA, object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { if ((sslPolicyErrors & (SslPolicyErrors.RemoteCertificateNameMismatch | SslPolicyErrors.RemoteCertificateNotAvailable)) > 0) { return(false); } X509Chain customChain = new X509Chain(false); customChain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; customChain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority; customChain.ChainPolicy.ExtraStore.Add(ourCA); if (!customChain.Build(chain.ChainElements[0].Certificate)) { return(false); } var chainElements = customChain.ChainElements; bool valid = chainElements[chainElements.Count - 1].Certificate.Thumbprint == ourCA.Thumbprint; customChain.Reset(); return(valid); }
public void Reset() { X509Chain c = new X509Chain(); c.ChainPolicy.ApplicationPolicy.Add(new Oid("1.2.3")); c.ChainPolicy.CertificatePolicy.Add(new Oid("1.2.4")); c.ChainPolicy.ExtraStore.AddRange(collection); c.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain; c.ChainPolicy.RevocationMode = X509RevocationMode.Offline; c.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(1000); c.ChainPolicy.VerificationFlags = X509VerificationFlags.IgnoreWrongUsage; c.ChainPolicy.VerificationTime = DateTime.MinValue; c.Reset(); // resetting the chain doesn't reset the policy Assert.AreEqual(1, c.ChainPolicy.ApplicationPolicy.Count, "ApplicationPolicy"); Assert.AreEqual(1, c.ChainPolicy.CertificatePolicy.Count, "CertificatePolicy"); Assert.AreEqual(2, c.ChainPolicy.ExtraStore.Count, "ExtraStore"); Assert.AreEqual(X509RevocationFlag.EntireChain, c.ChainPolicy.RevocationFlag, "RevocationFlag"); Assert.AreEqual(X509RevocationMode.Offline, c.ChainPolicy.RevocationMode, "RevocationMode"); Assert.AreEqual(1000, c.ChainPolicy.UrlRetrievalTimeout.Ticks, "UrlRetrievalTimeout"); Assert.AreEqual(X509VerificationFlags.IgnoreWrongUsage, c.ChainPolicy.VerificationFlags, "VerificationFlags"); Assert.AreEqual(DateTime.MinValue, c.ChainPolicy.VerificationTime, "VerificationTime"); }
protected X509Certificate SelectClientCertificate(string[] acceptableIssuers) { if (Settings.DisallowUnauthenticatedCertificateRequest && !IsAuthenticated) { return(null); } if (RemoteCertificate == null) { throw new TlsException(AlertDescription.InternalError, "Cannot request client certificate before receiving one from the server."); } /* * We need to pass null to the user selection callback during the initial handshake, to allow the callback to distinguish * between an authenticated and unauthenticated session. */ X509Certificate certificate; var selected = certificateValidator.SelectClientCertificate( TargetHost, ClientCertificates, IsAuthenticated ? RemoteCertificate : null, acceptableIssuers, out certificate); if (selected) { return(certificate); } if (ClientCertificates == null || ClientCertificates.Count == 0) { return(null); } /* * .NET actually scans the entire collection to ensure the selected certificate has a private key in it. * * However, since we do not support private key retrieval from the key store, we require all certificates * to have a private key in them (explicitly or implicitly via OS X keychain lookup). */ if (acceptableIssuers == null || acceptableIssuers.Length == 0) { return(ClientCertificates [0]); } // Copied from the referencesource implementation in referencesource/System/net/System/Net/_SecureChannel.cs. for (int i = 0; i < ClientCertificates.Count; i++) { var certificate2 = ClientCertificates[i] as X509Certificate2; if (certificate2 == null) { continue; } X509Chain chain = null; try { chain = new X509Chain(); chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; chain.ChainPolicy.VerificationFlags = X509VerificationFlags.IgnoreInvalidName; chain.Build(certificate2); // // We ignore any errors happened with chain. // Consider: try to locate the "best" client cert that has no errors and the lognest validity internal // if (chain.ChainElements.Count == 0) { continue; } for (int ii = 0; ii < chain.ChainElements.Count; ++ii) { var issuer = chain.ChainElements[ii].Certificate.Issuer; if (Array.IndexOf(acceptableIssuers, issuer) != -1) { return(certificate2); } } } catch { ; // ignore errors } finally { if (chain != null) { chain.Reset(); } } } // No certificate matches. return(null); }
/// <summary> /// Submits HTTP request to a remote server and updates current object instance. /// </summary> public void SendRequest() { if (Request != null) { List <String> san = new List <String>(); X509Chain Chain = new X509Chain(!UserContext); Pkcs7Chain = new X509Certificate2Collection(); // add inline delegate definition ServicePointManager.ServerCertificateValidationCallback = delegate(Object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { // check if web server returns multiple certificates if (chain.ChainElements.Count > 1) { foreach (X509ChainElement item in chain.ChainElements) { Pkcs7Chain.Add(item.Certificate); // add each certificate to X509Chain.ExtraStore, so certificate chaining engine // will be able to use them for chain building Chain.ChainPolicy.ExtraStore.Add(item.Certificate); } } if (((Int32)sslPolicyErrors & (Int32)SslPolicyErrors.RemoteCertificateNameMismatch) == 0) { NameMatch = true; } return(true); }; try { Response = (HttpWebResponse)Request.GetResponse(); ReturnedUri = Response.ResponseUri; if (Request.ServicePoint.Certificate != null) { Certificate = new X509Certificate2(Request.ServicePoint.Certificate); Subject = Certificate.SubjectName; Issuer = Certificate.IssuerName; if (Certificate.Extensions.Count > 0) { foreach (X509Extension item in Certificate.Extensions) { if (item.Oid.Value == X509CertExtensions.X509SubjectAlternativeNames) { san.AddRange(item.Format(false).Split(new [] { ", " }, StringSplitOptions.RemoveEmptyEntries)); } } } SubjectAlternativeNames = san.ToArray(); // add other settings for X509Chain and validate server certificate. Chain.ChainPolicy.ApplicationPolicy.Add(new Oid("1.3.6.1.5.5.7.3.1")); CertificateIsValid = Chain.Build(Certificate); ErrorInformation = Chain.ChainStatus; } } catch { if (!Request.HaveResponse) { throw; } } finally { Chain.Reset(); if (Response.ContentLength > 0) { Response.Close(); } ServicePointManager.ServerCertificateValidationCallback = null; } } else { throw new UninitializedObjectException(); } }
/// <summary> /// Checks a certificate status in a CRL. /// </summary> /// <param name="certificate">The certificate to check</param> /// <returns>The RevocationResponse object that contains the result</returns> public RevocationResponse CheckCertificate(X509Certificate2 certificate) { /* * Assumptions: * - Certificate has an CRL Distribution Points extension value. * - An HTTP distribution point is present. */ // create RevocationResponse and set default values RevocationResponse response = new RevocationResponse(); response.IsValid = true; response.NextUpdate = DateTime.MinValue; if (certificate != null) { X509Chain x509Chain = new X509Chain(); x509Chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; x509Chain.Build(certificate); // Iterate though the chain, to get the certificate list X509ChainElementCollection x509ChainElementCollection = x509Chain.ChainElements; X509ChainElementEnumerator enumerator = x509ChainElementCollection.GetEnumerator(); X509ChainElement x509ChainElement; X509Certificate2 x509Certificate2 = null; IDictionary <string, X509Certificate2> map = new Dictionary <string, X509Certificate2>(); IList <X509Certificate2> list = new List <X509Certificate2>(); while (enumerator.MoveNext()) { x509ChainElement = enumerator.Current; x509Certificate2 = x509ChainElement.Certificate; list.Add(x509Certificate2); } // now we have a list of the certificate chain // list[0] -> the function certificate // list[0 .. lsit.Count] -> middel certificates // oces1 : none middle certificate exist // oces2 : one middle certificate exist // list[list.Count] - > root certificate // we needed to validate all certificates, except the root certificates // The question wheather the root certificates is trusted, is validated in MultipleRootX509CertificateValidator // However - In the case where the root certificate is not installed, // the chain list will only be 1 length, so no validation is perfored at all. int index = 0; //bool chainValid = true; while (index < (list.Count - 1) && response.IsValid == true) { // this.logger.Info("CRL validation the certificate: " + list[index].Subject); // Retrieve URL distribution points List <Uri> URLs = this.GetURLs(list[index]); // The list should only contain one element // so we are only interesting in the first CRL list if (URLs.Count > 0) { Uri url = URLs[0]; CrlInstance crl = this.GetInstance(url); try { if (!crl.IsRevoked(certificate)) { // so the certificate is not revoked. // remember, that the issueing certificate could be revoked. // So the next update must be the earlist of the all response.IsValid = true; if (response.NextUpdate == DateTime.MinValue) { response.NextUpdate = crl.getNextUpdate(); } else if (response.NextUpdate < crl.getNextUpdate()) { // no new update // the already registrated 'NextUpdate' is before the crl.getNextUpdate } else { // new update time // The already registrated 'NextUpdate', is greater (futher in the future) then crl.getNextUpdate // so we use the crl.getNextUpdate as next update response.NextUpdate = crl.getNextUpdate(); } } else { response.IsValid = false; } } catch (CheckCertificateRevokedUnexpectedException exception) { // could not validate the certificate - so i don't trust it response.Exception = exception; response.IsValid = false; } } else { // url server not identified, so we don't trust this certificate response.IsValid = false; } // increase the index, to check the next certificate index++; } // all the certificate in the chain is now checked. if (response.IsValid == true) { response.RevocationCheckStatus = RevocationCheckStatus.AllChecksPassed; } else { response.RevocationCheckStatus = RevocationCheckStatus.CertificateRevoked; } x509Chain.Reset(); } else { response.IsValid = false; response.Exception = new CheckCertificateRevokedUnexpectedException(new Exception("Error during CRL lookup. The certificate is null"));//did not have any CRL DistPoints. Certificate: " + certificate)); response.RevocationCheckStatus = RevocationCheckStatus.UnknownIssue; } return(response); }
/// <summary> /// Validate the PC-EFTPOS Cloud server certificate. /// </summary> /// <returns>TRUE if the certificate is valid, FALSE otherwise</returns> bool RemoteCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { #if (DEBUG) return(true); #endif // Certificate chain is valid via a commercial 3rd party chain if (sslPolicyErrors == SslPolicyErrors.None) { Log(LogLevel.Info, tr => tr.Set("Remote certificate validated successfull by installed CA")); return(true); } // Certificate has an invalid CN or isn't available from the server if (sslPolicyErrors == SslPolicyErrors.RemoteCertificateNotAvailable || sslPolicyErrors == SslPolicyErrors.RemoteCertificateNameMismatch) { LogRemoteCertificateFailure(certificate, chain, sslPolicyErrors); return(false); } // The certificate is invalid due to an invalid chain. If we have included custom certificates we can attempt to validate here if (sslPolicyErrors == SslPolicyErrors.RemoteCertificateChainErrors && CustomeRootCerts?.Count > 0) { // Load custom certificates var x509Certificates = new List <X509Certificate2>(); foreach (var certFilename in CustomeRootCerts) { try { x509Certificates.Add(new X509Certificate2(certFilename)); } catch (System.Security.Cryptography.CryptographicException e) { Log(LogLevel.Error, tr => tr.Set($"Error loading certificate ({certFilename})", e)); return(false); } } var c = new X509Chain(); try { c.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; c.ChainPolicy.VerificationFlags = X509VerificationFlags.IgnoreWrongUsage; c.ChainPolicy.ExtraStore.AddRange(x509Certificates.ToArray()); // Check if the chain is valid if (c.Build((X509Certificate2)certificate)) { Log(LogLevel.Info, tr => tr.Set($"Remote certificate validated successfull by custom cert chain")); return(true); } // The chain may not be valid, but if the only fault is an UntrustedRoot we can check if we have the custom root else { if (c?.ChainStatus?.Length > 0 && c?.ChainStatus[0].Status == X509ChainStatusFlags.UntrustedRoot) { var root = c.ChainElements[c.ChainElements.Count - 1]; if (x509Certificates.Find(x509Certificate => x509Certificate.Thumbprint == root.Certificate.Thumbprint) != null) { Log(LogLevel.Info, tr => tr.Set($"Remote certificate validated successfull by custom cert chain and root")); return(true); } } } } finally { c.Reset(); } } LogRemoteCertificateFailure(certificate, chain, sslPolicyErrors); return(false); }
/// <summary> /// Validate the <see cref="X509Certificate2"/> for PSD2 compliance. /// </summary> /// <param name="certificate"></param> /// <param name="type">QC Type identifier. qSeal, qSign, Web. If passed null checks any of the valid ones</param> /// <param name="errors"></param> public bool Validate(X509Certificate2 certificate, X509Certificates.QcTypeIdentifiers?type, out IEnumerable <string> errors) { var errorList = new List <string>(); errors = errorList; var authorityKeyId = certificate.GetAuthorityKeyIdentifier(); if (string.IsNullOrEmpty(authorityKeyId)) { errorList.Add("Missing authority Key Identifier extension"); } var qcStatements = certificate.GetQualifiedCertificateStatements(); if (qcStatements == null) { errorList.Add("Missing the QcStatements X509Certivicate extension"); } else { if (!qcStatements.IsCompliant) { errorList.Add($"Although the certificate has the QcStatements X509Certivicate extension it is not a compliant \"European Qualified Certificate\". "); } if (qcStatements?.Psd2Type == null) { errorList.Add("This is not a valid QWAC or QCseal. Missing the PSD2 type QcStatement"); } if (type.HasValue && type.Value != qcStatements.Type) { errorList.Add($"{qcStatements.Type} is not a valid QcTypeIdentifier for the current use of this certificate. Expected option {type}"); } else if ((int)qcStatements.Type < 0 && 3 < (int)qcStatements.Type) { errorList.Add($"{qcStatements.Type} is not a valid QcTypeIdentifier. Valid options include {QcTypeIdentifiers.Web}, {QcTypeIdentifiers.eSeal} and {QcTypeIdentifiers.eSign}"); } if (!qcStatements.Psd2Type.Roles.Any()) { errorList.Add("There are no roles defined in this certificate"); } //if (!qcStatements.Psd2Type.AuthorizationId.IsValid) { // errorList.Add($"The NCAId is not in a valid format {qcStatements.Psd2Type.AuthorizationId}"); //} } var accessDescriptions = certificate.GetAuthorityInformationAccess(); if (accessDescriptions == null || !accessDescriptions.Any()) { errorList.Add($"There is no Authority Information Access extension inside the certificate."); } var policies = certificate.GetCertificatePolicies(); if (policies == null || !policies.Any(x => x.IsEUQualifiedCertificate)) { errorList.Add($"There is no Certificate Policy that identifies the current certificate as EU Qualified. There should be one in every eIDAs cert. Acceptable policy identifiers include: QCP-n, QCP-l, QCP-n-qscd, QCP-l-qscd, QCP-w"); } var crlDistributionPoints = certificate.GetCRLDistributionPoints(); if (crlDistributionPoints == null || !crlDistributionPoints.Any()) { errorList.Add($"There is no CRL distribution points extension inside the certificate."); } var authorizationId = qcStatements.Psd2Type.AuthorizationId; var organizationId = certificate.GetCABForumOrganizationIdentifier(); var subjectOrgId = certificate.GetSubjectBuilder().GetOrganizationIdentifier(); if (string.IsNullOrEmpty(subjectOrgId)) { errorList.Add("The subject must contain the Organization Identifier as defined in PSD2 by the 2.5.4.97 Oid"); } if (organizationId == null) { errorList.Add("There is no CA/Browser Forum OrganizationIdentifier extension inside the certificate. Oid 2.23.140.3.1"); } if (!string.IsNullOrEmpty(subjectOrgId) && organizationId != null) { if (!NCAId.TryParse(organizationId.ToString(), out var id) || !id.IsValid) { errorList.Add($"The organizationId inside the CA/Browser Forum OrganizationIdentifier has an invalid format. {organizationId}"); } else if (!id.Equals(subjectOrgId)) { errorList.Add($"The organizationId inside the CA/Browser Forum OrganizationIdentifier is not the same with the one in the subject, {organizationId} != {subjectOrgId}"); } } var chain = new X509Chain(); chain.ChainPolicy.RevocationMode = X509RevocationMode.Online; chain.Build(certificate); X509Certificate2 issuer = null; if (chain.ChainElements.Count > 1) { issuer = chain.ChainElements[1].Certificate; } chain.Reset(); return(errorList.Count == 0); }
private bool AcquireClientCredentials(ref byte[] thumbPrint) { X509Certificate certificate = null; ArrayList list = new ArrayList(); string[] acceptableIssuers = null; bool flag = false; if (this.m_CertSelectionDelegate != null) { if (acceptableIssuers == null) { acceptableIssuers = this.GetIssuers(); } X509Certificate2 remoteCertificate = null; try { X509Certificate2Collection certificates; remoteCertificate = this.GetRemoteCertificate(out certificates); certificate = this.m_CertSelectionDelegate(this.m_HostName, this.ClientCertificates, remoteCertificate, acceptableIssuers); } finally { if (remoteCertificate != null) { remoteCertificate.Reset(); } } if (certificate != null) { if (this.m_CredentialsHandle == null) { flag = true; } list.Add(certificate); if (Logging.On) { Logging.PrintInfo(Logging.Web, this, SR.GetString("net_log_got_certificate_from_delegate")); } } else if (this.ClientCertificates.Count == 0) { if (Logging.On) { Logging.PrintInfo(Logging.Web, this, SR.GetString("net_log_no_delegate_and_have_no_client_cert")); } flag = true; } else if (Logging.On) { Logging.PrintInfo(Logging.Web, this, SR.GetString("net_log_no_delegate_but_have_client_cert")); } } else if (((this.m_CredentialsHandle == null) && (this.m_ClientCertificates != null)) && (this.m_ClientCertificates.Count > 0)) { certificate = this.ClientCertificates[0]; flag = true; if (certificate != null) { list.Add(certificate); } if (Logging.On) { Logging.PrintInfo(Logging.Web, this, SR.GetString("net_log_attempting_restart_using_cert", new object[] { (certificate == null) ? "null" : certificate.ToString(true) })); } } else if ((this.m_ClientCertificates != null) && (this.m_ClientCertificates.Count > 0)) { if (acceptableIssuers == null) { acceptableIssuers = this.GetIssuers(); } if (Logging.On) { if ((acceptableIssuers == null) || (acceptableIssuers.Length == 0)) { Logging.PrintInfo(Logging.Web, this, SR.GetString("net_log_no_issuers_try_all_certs")); } else { Logging.PrintInfo(Logging.Web, this, SR.GetString("net_log_server_issuers_look_for_matching_certs", new object[] { acceptableIssuers.Length })); } } for (int j = 0; j < this.m_ClientCertificates.Count; j++) { if ((acceptableIssuers != null) && (acceptableIssuers.Length != 0)) { X509Certificate2 certificate3 = null; X509Chain chain = null; try { certificate3 = MakeEx(this.m_ClientCertificates[j]); if (certificate3 == null) { continue; } chain = new X509Chain { ChainPolicy = { RevocationMode = X509RevocationMode.NoCheck, VerificationFlags = X509VerificationFlags.IgnoreInvalidName } }; chain.Build(certificate3); bool flag2 = false; if (chain.ChainElements.Count > 0) { for (int k = 0; k < chain.ChainElements.Count; k++) { string issuer = chain.ChainElements[k].Certificate.Issuer; flag2 = Array.IndexOf <string>(acceptableIssuers, issuer) != -1; if (flag2) { break; } } } if (!flag2) { continue; } } finally { if (chain != null) { chain.Reset(); } if ((certificate3 != null) && (certificate3 != this.m_ClientCertificates[j])) { certificate3.Reset(); } } } if (Logging.On) { Logging.PrintInfo(Logging.Web, this, SR.GetString("net_log_selected_cert", new object[] { this.m_ClientCertificates[j].ToString(true) })); } list.Add(this.m_ClientCertificates[j]); } } X509Certificate2 certificate4 = null; certificate = null; if (Logging.On) { Logging.PrintInfo(Logging.Web, this, SR.GetString("net_log_n_certs_after_filtering", new object[] { list.Count })); if (list.Count != 0) { Logging.PrintInfo(Logging.Web, this, SR.GetString("net_log_finding_matching_certs")); } } for (int i = 0; i < list.Count; i++) { certificate = list[i] as X509Certificate; certificate4 = this.EnsurePrivateKey(certificate); if (certificate4 != null) { break; } certificate = null; certificate4 = null; } try { byte[] buffer = (certificate4 == null) ? null : certificate4.GetCertHash(); SafeFreeCredentials credentials = SslSessionsCache.TryCachedCredential(buffer, this.m_ProtocolFlags, this.m_EncryptionPolicy); if ((flag && (credentials == null)) && (certificate4 != null)) { if (certificate != certificate4) { certificate4.Reset(); } buffer = null; certificate4 = null; certificate = null; } if (credentials != null) { if (Logging.On) { Logging.PrintInfo(Logging.Web, SR.GetString("net_log_using_cached_credential")); } this.m_CredentialsHandle = credentials; this.m_SelectedClientCertificate = certificate; return(true); } SecureCredential secureCredential = new SecureCredential(4, certificate4, SecureCredential.Flags.NoDefaultCred | SecureCredential.Flags.ValidateManual, this.m_ProtocolFlags, this.m_EncryptionPolicy); this.m_CredentialsHandle = this.AcquireCredentialsHandle(CredentialUse.Outbound, ref secureCredential); thumbPrint = buffer; this.m_SelectedClientCertificate = certificate; } finally { if ((certificate4 != null) && (certificate != certificate4)) { certificate4.Reset(); } } return(false); }