Exemple #1
0
        //
        // Verifies whether a certificate is valid for the specified policy.
        // S_OK means the certificate is valid for the specified policy.
        // S_FALSE means the certificate is invalid for the specified policy.
        // Anything else is an error.
        //

        internal static unsafe int VerifyCertificate(SafeCertContextHandle pCertContext,
                                                     OidCollection applicationPolicy,
                                                     OidCollection certificatePolicy,
                                                     X509RevocationMode revocationMode,
                                                     X509RevocationFlag revocationFlag,
                                                     DateTime verificationTime,
                                                     TimeSpan timeout,
                                                     X509Certificate2Collection extraStore,
                                                     IntPtr pszPolicy,
                                                     IntPtr pdwErrorStatus)
        {
            if (pCertContext == null || pCertContext.IsInvalid)
            {
                throw new ArgumentException("pCertContext");
            }

            CAPI.CERT_CHAIN_POLICY_PARA   PolicyPara   = new CAPI.CERT_CHAIN_POLICY_PARA(Marshal.SizeOf(typeof(CAPI.CERT_CHAIN_POLICY_PARA)));
            CAPI.CERT_CHAIN_POLICY_STATUS PolicyStatus = new CAPI.CERT_CHAIN_POLICY_STATUS(Marshal.SizeOf(typeof(CAPI.CERT_CHAIN_POLICY_STATUS)));

            // Build the chain.
            SafeCertChainHandle pChainContext = SafeCertChainHandle.InvalidHandle;
            int hr = X509Chain.BuildChain(new IntPtr(CAPI.HCCE_CURRENT_USER),
                                          pCertContext,
                                          extraStore,
                                          applicationPolicy,
                                          certificatePolicy,
                                          revocationMode,
                                          revocationFlag,
                                          verificationTime,
                                          timeout,
                                          ref pChainContext);

            if (hr != CAPI.S_OK)
            {
                return(hr);
            }

            // Verify the chain using the specified policy.
            if (CAPI.CertVerifyCertificateChainPolicy(pszPolicy, pChainContext, ref PolicyPara, ref PolicyStatus))
            {
                if (pdwErrorStatus != IntPtr.Zero)
                {
                    *(uint *)pdwErrorStatus = PolicyStatus.dwError;
                }

                if (PolicyStatus.dwError != 0)
                {
                    return(CAPI.S_FALSE);
                }
            }
            else
            {
                // The API failed.
                return(Marshal.GetHRForLastWin32Error());
            }

            return(CAPI.S_OK);
        }
        public bool Build(X509Certificate2 certificate)
        {
            lock (m_syncRoot) {
                if (certificate == null || certificate.CertContext.IsInvalid)
                {
                    throw new ArgumentException(SR.GetString(SR.Cryptography_InvalidContextHandle), "certificate");
                }

                // Chain building opens and enumerates the root store to see if the root of the chain is trusted.
                StorePermission sp = new StorePermission(StorePermissionFlags.OpenStore | StorePermissionFlags.EnumerateCertificates);
                sp.Demand();

                X509ChainPolicy chainPolicy = this.ChainPolicy;
                if (chainPolicy.RevocationMode == X509RevocationMode.Online)
                {
                    if (certificate.Extensions[CAPI.szOID_CRL_DIST_POINTS] != null ||
                        certificate.Extensions[CAPI.szOID_AUTHORITY_INFO_ACCESS] != null)
                    {
                        // If there is a CDP or AIA extension, we demand unrestricted network access and store add permission
                        // since CAPI can download certificates into the CA store from the network.
                        PermissionSet ps = new PermissionSet(PermissionState.None);
                        ps.AddPermission(new WebPermission(PermissionState.Unrestricted));
                        ps.AddPermission(new StorePermission(StorePermissionFlags.AddToStore));
                        ps.Demand();
                    }
                }

                Reset();
                int hr = BuildChain(m_useMachineContext ? new IntPtr(CAPI.HCCE_LOCAL_MACHINE) : new IntPtr(CAPI.HCCE_CURRENT_USER),
                                    certificate.CertContext,
                                    chainPolicy.ExtraStore,
                                    chainPolicy.ApplicationPolicy,
                                    chainPolicy.CertificatePolicy,
                                    chainPolicy.RevocationMode,
                                    chainPolicy.RevocationFlag,
                                    chainPolicy.VerificationTime,
                                    chainPolicy.UrlRetrievalTimeout,
                                    ref m_safeCertChainHandle);

                if (hr != CAPI.S_OK)
                {
                    return(false);
                }

                // Init.
                Init();

                // Verify the chain using the specified policy.
                CAPI.CERT_CHAIN_POLICY_PARA   PolicyPara   = new CAPI.CERT_CHAIN_POLICY_PARA(Marshal.SizeOf(typeof(CAPI.CERT_CHAIN_POLICY_PARA)));
                CAPI.CERT_CHAIN_POLICY_STATUS PolicyStatus = new CAPI.CERT_CHAIN_POLICY_STATUS(Marshal.SizeOf(typeof(CAPI.CERT_CHAIN_POLICY_STATUS)));

                PolicyPara.dwFlags = (uint)chainPolicy.VerificationFlags;

                if (!CAPI.CertVerifyCertificateChainPolicy(new IntPtr(CAPI.CERT_CHAIN_POLICY_BASE),
                                                           m_safeCertChainHandle,
                                                           ref PolicyPara,
                                                           ref PolicyStatus))
                {
                    // The API failed.
                    throw new CryptographicException(Marshal.GetLastWin32Error());
                }

                CAPI.SetLastError(PolicyStatus.dwError);
                return(PolicyStatus.dwError == 0);
            }
        }
        public bool Build(X509Certificate2 certificate)
        {
            if (certificate == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("certificate");
            }
            if (certificate.Handle == IntPtr.Zero)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("certificate", SR.GetString(SR.ArgumentInvalidCertificate));
            }

            SafeCertChainHandle safeCertChainHandle = SafeCertChainHandle.InvalidHandle;
            X509ChainPolicy     chainPolicy         = this.ChainPolicy;

            chainPolicy.VerificationTime = DateTime.Now;
            if (chainPolicy.RevocationMode == X509RevocationMode.Online)
            {
                if (certificate.Extensions[CAPI.szOID_CRL_DIST_POINTS] != null ||
                    certificate.Extensions[CAPI.szOID_AUTHORITY_INFO_ACCESS] != null)
                {
                    // If there is a CDP or AIA extension, we demand unrestricted network access and store add permission
                    // since CAPI can download certificates into the CA store from the network.
                    PermissionSet ps = new PermissionSet(PermissionState.None);
                    ps.AddPermission(new WebPermission(PermissionState.Unrestricted));
                    ps.AddPermission(new StorePermission(StorePermissionFlags.AddToStore));
                    ps.Demand();
                }
            }

            BuildChain(this.useMachineContext ? new IntPtr(CAPI.HCCE_LOCAL_MACHINE) : new IntPtr(CAPI.HCCE_CURRENT_USER),
                       certificate.Handle,
                       chainPolicy.ExtraStore,
                       chainPolicy.ApplicationPolicy,
                       chainPolicy.CertificatePolicy,
                       chainPolicy.RevocationMode,
                       chainPolicy.RevocationFlag,
                       chainPolicy.VerificationTime,
                       chainPolicy.UrlRetrievalTimeout,
                       out safeCertChainHandle);

            // Verify the chain using the specified policy.
            CAPI.CERT_CHAIN_POLICY_PARA   PolicyPara   = new CAPI.CERT_CHAIN_POLICY_PARA(Marshal.SizeOf(typeof(CAPI.CERT_CHAIN_POLICY_PARA)));
            CAPI.CERT_CHAIN_POLICY_STATUS PolicyStatus = new CAPI.CERT_CHAIN_POLICY_STATUS(Marshal.SizeOf(typeof(CAPI.CERT_CHAIN_POLICY_STATUS)));

            // Ignore peertrust.  Peer trust caused the chain to succeed out-of-the-box in Vista.
            // This new flag is only available in Vista.
            PolicyPara.dwFlags = (uint)chainPolicy.VerificationFlags | CAPI.CERT_CHAIN_POLICY_IGNORE_PEER_TRUST_FLAG;

            if (!CAPI.CertVerifyCertificateChainPolicy(new IntPtr(this.chainPolicyOID),
                                                       safeCertChainHandle,
                                                       ref PolicyPara,
                                                       ref PolicyStatus))
            {
                int error = Marshal.GetLastWin32Error();
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CryptographicException(error));
            }

            if (PolicyStatus.dwError != CAPI.S_OK)
            {
                int error = (int)PolicyStatus.dwError;
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenValidationException(SR.GetString(SR.X509ChainBuildFail,
                                                                                                                            SecurityUtils.GetCertificateId(certificate), new CryptographicException(error).Message)));
            }

            return(true);
        }