//----------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------- namespace System.IdentityModel { using System; using System.IdentityModel.Selectors; using System.Security.Cryptography.X509Certificates; using System.ServiceModel.Security; /// /// This class wraps the four WCF validator types (Peer, Chain, PeerOrChain, and None). /// This class also resets the validation time each time a certificate is validated, to fix a .NET issue /// where certificates created after the validator is created will not chain. /// internal class X509CertificateValidatorEx : X509CertificateValidator { private X509CertificateValidationMode certificateValidationMode; private X509ChainPolicy chainPolicy; private X509CertificateValidator validator; public X509CertificateValidatorEx( X509CertificateValidationMode certificateValidationMode, X509RevocationMode revocationMode, StoreLocation trustedStoreLocation) { this.certificateValidationMode = certificateValidationMode; switch (this.certificateValidationMode) { case X509CertificateValidationMode.None: { this.validator = X509CertificateValidator.None; break; } case X509CertificateValidationMode.PeerTrust: { this.validator = X509CertificateValidator.PeerTrust; break; } case X509CertificateValidationMode.ChainTrust: { bool useMachineContext = trustedStoreLocation == StoreLocation.LocalMachine; this.chainPolicy = new X509ChainPolicy(); this.chainPolicy.RevocationMode = revocationMode; this.validator = X509CertificateValidator.CreateChainTrustValidator(useMachineContext, this.chainPolicy); break; } case X509CertificateValidationMode.PeerOrChainTrust: { bool useMachineContext = trustedStoreLocation == StoreLocation.LocalMachine; this.chainPolicy = new X509ChainPolicy(); this.chainPolicy.RevocationMode = revocationMode; this.validator = X509CertificateValidator.CreatePeerOrChainTrustValidator(useMachineContext, this.chainPolicy); break; } case X509CertificateValidationMode.Custom: default: throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ID4256))); } } public override void Validate(X509Certificate2 certificate) { if (this.certificateValidationMode == X509CertificateValidationMode.ChainTrust || this.certificateValidationMode == X509CertificateValidationMode.PeerOrChainTrust) { // This is needed due to a .NET issue where the validation time is not properly set, // causing certificates created after the creation of the validator to fail chain trust. this.chainPolicy.VerificationTime = DateTime.Now; } this.validator.Validate(certificate); } } }