예제 #1
0
        /// <summary>
        /// Validates a certificate by walking the certificate chain for all trust anchor chain, validating the leaf certificate against the chain.
        /// </summary>
        /// <remarks>Currently, all intermediate certificates must be stored in the system.</remarks>
        /// <param name="certificate">The leaf <see cref="X509Certificate2"/> to validate</param>
        /// <param name="anchors">The collection of certificates representing anchors or roots of trust.</param>
        /// <returns><c>true</c> if at least one anchor has a valid chain of certs that verify trust in the leaf certificate,
        /// <c>false</c> if no anchors validate trust in the leaf cert.</returns>
        public bool IsTrustedCertificate(X509Certificate2 certificate, X509Certificate2Collection anchors)
        {
            if (certificate == null)
            {
                throw new ArgumentNullException("certificate");
            }

            // if there are no anchors we should always fail
            if (CollectionExtensions.IsNullOrEmpty(anchors))
            {
                this.NotifyUntrusted(certificate);
                return false;
            }

            X509Chain chainBuilder = new X509Chain();
            chainBuilder.ChainPolicy = m_policy.Clone();
            
            chainBuilder.ChainPolicy.ExtraStore.Add(anchors);
            if (this.HasCertificateResolver)
            {
                this.ResolveIntermediateIssuers(certificate, chainBuilder.ChainPolicy.ExtraStore);
            }
            
            try
            {
                // We're using the system class as a helper to merely build the chain
                // However, we will review each item in the chain ourselves, because we have our own rules...
                chainBuilder.Build(certificate);
                X509ChainElementCollection chainElements = chainBuilder.ChainElements;

                // If we don't have a trust chain, then we obviously have a problem...
                if (chainElements.IsNullOrEmpty())
                {
                    this.NotifyUntrusted(certificate);
                    return false;
                }

                // walk the chain starting at the leaf and see if we hit any issues before the anchor
                foreach (X509ChainElement chainElement in chainElements)
                {                
                    if (this.ChainElementHasProblems(chainElement))
                    {
                        this.NotifyProblem(chainElement);
                        
                        // Whoops... problem with at least one cert in the chain. Stop immediately
                        return false;
                    }

                    bool isAnchor = (anchors.FindByThumbprint(chainElement.Certificate.Thumbprint) != null);
                    if (isAnchor)
                    {
                        // Found a valid anchor!
                        // Because we found an anchor we trust, we can now trust the entire trust chain
                        return true;
                    }
                }
            }
            catch(Exception ex)
            {
                this.NotifyError(certificate, ex);
                // just eat it and drop out to return false
            }
            
            this.NotifyUntrusted(certificate);
            return (false);
        }
예제 #2
0
        private void VerifyValidCert(X509Certificate2Collection source, X509Certificate2Collection cached)
        {
            Assert.NotNull(source);
            Assert.NotNull(cached);
            Assert.True(cached.Count > 0);
            Assert.Equal(source.Count, cached.Count);

            source.Enumerate().All((x) => cached.FindByThumbprint(x.Thumbprint) != null);
            cached.Enumerate().All((x) => source.FindByThumbprint(x.Thumbprint) != null);
        }