File: FrameworkFork\System.ServiceModel\System\IdentityModel\Selectors\X509CertificateValidator.cs
Web Access
Project: src\src\dotnet-svcutil\lib\src\dotnet-svcutil-lib.csproj (dotnet-svcutil-lib)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System.Diagnostics.Contracts;
using System.IdentityModel.Tokens;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
using System.Text;
 
namespace System.IdentityModel.Selectors
{
    public abstract class X509CertificateValidator
    {
        private static X509CertificateValidator s_chainTrust;
        private static X509CertificateValidator s_none;
 
        public static X509CertificateValidator None
        {
            get
            {
                if (s_none == null)
                    s_none = new NoneX509CertificateValidator();
                return s_none;
            }
        }
 
        public static X509CertificateValidator ChainTrust
        {
            get
            {
                if (s_chainTrust == null)
                    s_chainTrust = new ChainTrustValidator();
                return s_chainTrust;
            }
        }
 
        public static X509CertificateValidator CreateChainTrustValidator(bool useMachineContext, X509ChainPolicy chainPolicy)
        {
            if (chainPolicy == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("chainPolicy");
            return new ChainTrustValidator(useMachineContext, chainPolicy, X509CertificateChain.DefaultChainPolicyOID);
        }
 
        public abstract void Validate(X509Certificate2 certificate);
 
        private class NoneX509CertificateValidator : X509CertificateValidator
        {
            public override void Validate(X509Certificate2 certificate)
            {
                if (certificate == null)
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("certificate");
            }
        }
 
        private class ChainTrustValidator : X509CertificateValidator
        {
            private bool _useMachineContext;
            private X509ChainPolicy _chainPolicy;
            private uint _chainPolicyOID = X509CertificateChain.DefaultChainPolicyOID;
 
            public ChainTrustValidator()
            {
                _chainPolicy = null;
            }
 
            public ChainTrustValidator(bool useMachineContext, X509ChainPolicy chainPolicy, uint chainPolicyOID)
            {
                Contract.Assert(useMachineContext == false, "CoreCLR does not have ctor allowing useMachineContext = true");
 
                _useMachineContext = useMachineContext;
                _chainPolicy = chainPolicy;
                _chainPolicyOID = chainPolicyOID;
            }
 
            public override void Validate(X509Certificate2 certificate)
            {
                if (certificate == null)
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("certificate");
 
                // implies _useMachineContext = false
                // ctor for X509Chain(_useMachineContext, _chainPolicyOID) not present in CoreCLR
                X509Chain chain = new X509Chain();
 
                if (_chainPolicy != null)
                {
                    chain.ChainPolicy = _chainPolicy;
                }
 
                if (!chain.Build(certificate))
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenValidationException(string.Format(SRServiceModel.X509ChainBuildFail,
                        SecurityUtils.GetCertificateId(certificate), GetChainStatusInformation(chain.ChainStatus))));
                }
            }
 
            private static string GetChainStatusInformation(X509ChainStatus[] chainStatus)
            {
                if (chainStatus != null)
                {
                    StringBuilder error = new StringBuilder(128);
                    for (int i = 0; i < chainStatus.Length; ++i)
                    {
                        error.Append(chainStatus[i].StatusInformation);
                        error.Append(" ");
                    }
                    return error.ToString();
                }
                return String.Empty;
            }
        }
    }
}