private unsafe uint[] GetChainErrors(string hostName, X509Chain chain, ref bool fatalError)
 {
     fatalError = false;
     SafeFreeCertChain chainContext = new SafeFreeCertChain(chain.ChainContext);
     ArrayList list = new ArrayList();
     uint errorCode = 0;
     ChainPolicyParameter cpp = new ChainPolicyParameter {
         cbSize = ChainPolicyParameter.StructSize,
         dwFlags = 0
     };
     SSL_EXTRA_CERT_CHAIN_POLICY_PARA ssl_extra_cert_chain_policy_para = new SSL_EXTRA_CERT_CHAIN_POLICY_PARA(false);
     cpp.pvExtraPolicyPara = &ssl_extra_cert_chain_policy_para;
     fixed (char* str = ((char*) hostName))
     {
         char* chPtr = str;
         if (ServicePointManager.CheckCertificateName)
         {
             ssl_extra_cert_chain_policy_para.pwszServerName = chPtr;
         }
     Label_006B:
         errorCode = VerifyChainPolicy(chainContext, ref cpp);
         uint num2 = (uint) MapErrorCode(errorCode);
         list.Add(errorCode);
         if (errorCode != 0)
         {
             if (num2 == 0)
             {
                 fatalError = true;
             }
             else
             {
                 cpp.dwFlags |= num2;
                 if ((errorCode == 0x800b010f) && ServicePointManager.CheckCertificateName)
                 {
                     ssl_extra_cert_chain_policy_para.fdwChecks = 0x1000;
                 }
                 goto Label_006B;
             }
         }
     }
     return (uint[]) list.ToArray(typeof(uint));
 }
Пример #2
0
        private uint[] GetChainErrors(string hostName, X509Chain chain, ref bool fatalError)
        {
            fatalError = false;
            SafeFreeCertChain chainContext= new SafeFreeCertChain(chain.ChainContext);
            ArrayList certificateProblems = new ArrayList();
            unsafe {
                uint status = 0;
                ChainPolicyParameter cppStruct = new ChainPolicyParameter();
                cppStruct.cbSize  = ChainPolicyParameter.StructSize;
                cppStruct.dwFlags = 0;

                SSL_EXTRA_CERT_CHAIN_POLICY_PARA eppStruct = new SSL_EXTRA_CERT_CHAIN_POLICY_PARA(false);
                cppStruct.pvExtraPolicyPara = &eppStruct;

                fixed (char* namePtr = hostName) {
                    if (ServicePointManager.CheckCertificateName){
                        eppStruct.pwszServerName = namePtr;
                    }

                    while (true) {
                        status = VerifyChainPolicy(chainContext, ref cppStruct);
                        uint ignoreErrorMask = (uint)MapErrorCode(status);

                        certificateProblems.Add(status);

                        if (status == 0) {  // No more problems with the certificate?
                            break;          // Then break out of the callback loop
                        }

                        if (ignoreErrorMask == 0) {  // Unrecognized error encountered
                            fatalError = true;
                            break;
                        }
                        else {
                            cppStruct.dwFlags |= ignoreErrorMask;
                            if ((CertificateProblem)status == CertificateProblem.CertCN_NO_MATCH && ServicePointManager.CheckCertificateName) {
                                eppStruct.fdwChecks = IgnoreUnmatchedCN;
                            }
                        }
                    }
                }
            }

            return (uint[]) certificateProblems.ToArray(typeof(uint));
        }
Пример #3
0
        internal static uint VerifyChainPolicy(SafeFreeCertChain chainContext, ref ChainPolicyParameter cpp) {
            GlobalLog.Enter("PolicyWrapper::VerifyChainPolicy", "chainContext="+ chainContext + ", options="+String.Format("0x{0:x}", cpp.dwFlags));
            ChainPolicyStatus status = new ChainPolicyStatus();
            status.cbSize = ChainPolicyStatus.StructSize;
            int errorCode =
                UnsafeNclNativeMethods.NativePKI.CertVerifyCertificateChainPolicy(
                    (IntPtr) ChainPolicyType.SSL,
                    chainContext,
                    ref cpp,
                    ref status);

            GlobalLog.Print("PolicyWrapper::VerifyChainPolicy() CertVerifyCertificateChainPolicy returned: " + errorCode);
#if TRAVE
            GlobalLog.Print("PolicyWrapper::VerifyChainPolicy() error code: " + status.dwError+String.Format(" [0x{0:x8}", status.dwError) + " " + SecureChannel.MapSecurityStatus(status.dwError) + "]");
#endif
            GlobalLog.Leave("PolicyWrapper::VerifyChainPolicy", status.dwError.ToString());
            return status.dwError;
        }
Пример #4
0
        internal bool VerifyRemoteCertificate(RemoteCertValidationCallback remoteCertValidationCallback)
        {
            GlobalLog.Enter("SecureChannel#" + ValidationHelper.HashString(this) + "::VerifyRemoteCertificate");
            SslPolicyErrors sslPolicyErrors = SslPolicyErrors.None;
            // we don't catch exceptions in this method, so it's safe for "accepted" be initialized with true
            bool success = false;

            X509Chain chain = null;
            X509Certificate2 remoteCertificateEx = null;

            try {
                X509Certificate2Collection remoteCertificateStore;
                remoteCertificateEx = GetRemoteCertificate(out remoteCertificateStore);
                m_IsRemoteCertificateAvailable = remoteCertificateEx != null;

                if (remoteCertificateEx == null)
                {
                    GlobalLog.Leave("SecureChannel#" + ValidationHelper.HashString(this) + "::VerifyRemoteCertificate (no remote cert)", (!m_RemoteCertRequired).ToString());
                    sslPolicyErrors |= SslPolicyErrors.RemoteCertificateNotAvailable;
                }
#if !MONO
                else
                {
                    chain = new X509Chain();
                    chain.ChainPolicy.RevocationMode = m_CheckCertRevocation? X509RevocationMode.Online : X509RevocationMode.NoCheck;
                    chain.ChainPolicy.RevocationFlag = X509RevocationFlag.ExcludeRoot;
                    if (remoteCertificateStore != null)
                        chain.ChainPolicy.ExtraStore.AddRange(remoteCertificateStore);

                    if (!chain.Build(remoteCertificateEx)       // Build failed on handle or on policy
                        && chain.ChainContext == IntPtr.Zero)   // Build failed to generate a valid handle
                    {
                        throw new CryptographicException(Marshal.GetLastWin32Error());
                    }

                    if (m_CheckCertName)
                    {
                        unsafe {
                            uint status = 0;
                            ChainPolicyParameter cppStruct = new ChainPolicyParameter();
                            cppStruct.cbSize  = ChainPolicyParameter.StructSize;
                            cppStruct.dwFlags = 0;


                            SSL_EXTRA_CERT_CHAIN_POLICY_PARA eppStruct = new SSL_EXTRA_CERT_CHAIN_POLICY_PARA(IsServer);
                            cppStruct.pvExtraPolicyPara = &eppStruct;

                            fixed (char* namePtr = m_HostName) {
                                eppStruct.pwszServerName = namePtr;
                                cppStruct.dwFlags |= (int) (IgnoreCertProblem.none & ~IgnoreCertProblem.invalid_name);

                                SafeFreeCertChain chainContext= new SafeFreeCertChain(chain.ChainContext);
                                status = PolicyWrapper.VerifyChainPolicy(chainContext, ref cppStruct);
                                if ((CertificateProblem) status ==  CertificateProblem.CertCN_NO_MATCH)
                                    sslPolicyErrors |= SslPolicyErrors.RemoteCertificateNameMismatch;
                            }
                        }
                    }

                    X509ChainStatus[] chainStatusArray = chain.ChainStatus;
                    if (chainStatusArray != null && chainStatusArray.Length != 0)
                        sslPolicyErrors |= SslPolicyErrors.RemoteCertificateChainErrors;

                }

                if (remoteCertValidationCallback != null) {
                    success = remoteCertValidationCallback(m_HostName, remoteCertificateEx, chain, sslPolicyErrors);
                } else {
                    if (sslPolicyErrors == SslPolicyErrors.RemoteCertificateNotAvailable && !m_RemoteCertRequired)
                        success = true;
                    else
                        success = (sslPolicyErrors == SslPolicyErrors.None);
                }
#else
		success = SSPIWrapper.CheckRemoteCertificate(m_SecurityContext);
#endif

                if (Logging.On) {
                    if (sslPolicyErrors != SslPolicyErrors.None)
                    {
                        Logging.PrintInfo(Logging.Web, this, SR.GetString(SR.net_log_remote_cert_has_errors));
                        if ((sslPolicyErrors & SslPolicyErrors.RemoteCertificateNotAvailable) != 0)
                            Logging.PrintInfo(Logging.Web, this, "\t" + SR.GetString(SR.net_log_remote_cert_not_available));
                        if ((sslPolicyErrors & SslPolicyErrors.RemoteCertificateNameMismatch) != 0)
                            Logging.PrintInfo(Logging.Web, this, "\t" + SR.GetString(SR.net_log_remote_cert_name_mismatch));
                        if ((sslPolicyErrors & SslPolicyErrors.RemoteCertificateChainErrors) != 0)
                            foreach (X509ChainStatus chainStatus in chain.ChainStatus)
                                Logging.PrintInfo(Logging.Web, this, "\t" + chainStatus.StatusInformation);
                    }
                    if (success)
                    {
                        if (remoteCertValidationCallback != null)
                            Logging.PrintInfo(Logging.Web, this, SR.GetString(SR.net_log_remote_cert_user_declared_valid));
                        else
                            Logging.PrintInfo(Logging.Web, this, SR.GetString(SR.net_log_remote_cert_has_no_errors));
                    }
                    else
                    {
                        if (remoteCertValidationCallback != null)
                            Logging.PrintInfo(Logging.Web, this, SR.GetString(SR.net_log_remote_cert_user_declared_invalid));
                    }
                }
                GlobalLog.Print("Cert Validation, remote cert = " + (remoteCertificateEx == null? "<null>": remoteCertificateEx.ToString(true)));
            }
            finally {
                // At least on Win2k server the chain is found to have dependancies on the original cert context.
                // So it should be closed first.
                if (chain != null) {
                    chain.Reset();
                }
                if (remoteCertificateEx != null)
                    remoteCertificateEx.Reset();
            }
            GlobalLog.Leave("SecureChannel#" + ValidationHelper.HashString(this) + "::VerifyRemoteCertificate", success.ToString());
            return success;
        }
            internal static X509CertificateCollection FindClientCertificates()
            {
                if (!ComNetOS.IsWin7orLater)
                {
                    throw new PlatformNotSupportedException();
                }

                X509CertificateCollection certificates = new X509CertificateCollection();

                X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
                store.Open(OpenFlags.MaxAllowed);

                int chainCount = 0;
                SafeFreeCertChainList chainList = null;
                SafeCertSelectCritera criteria = new SafeCertSelectCritera();
                try
                {
                    bool success = CertSelectCertificateChains(
                        IntPtr.Zero,
                        CertificateSelect.HasPrivateKey, 
                        IntPtr.Zero,
                        criteria.Count,  // DWORD
                        criteria, // PCCERT_SELECT_CRITERIA
                        store.StoreHandle, 
                        out chainCount, 
                        out chainList);

                    if (!success)
                    {
                        throw new Win32Exception(); // Calls GetLastError.
                    }

                    Debug.Assert(chainCount == 0 || !chainList.IsInvalid);

                    for (int i = 0; i < chainCount; i++)
                    {
                        // Resolve IntPtr in array.
                        using (SafeFreeCertChain chainRef = new SafeFreeCertChain(
                            Marshal.ReadIntPtr(chainList.DangerousGetHandle() 
                            + i * Marshal.SizeOf(typeof(IntPtr))), true))
                        {
                            Debug.Assert(!chainRef.IsInvalid);

                            // X509Chain will duplicate the chain by increasing its ref-count.
                            X509Chain chain = new X509Chain(chainRef.DangerousGetHandle());
                            
                            // Copy base cert from chain.
                            if (chain.ChainElements.Count > 0)
                            {
                                X509Certificate2 cert = chain.ChainElements[0].Certificate;
                                certificates.Add(cert);
                            }

                            // Remove the X509Chain's reference prior to releasing the Chain List.
                            chain.Reset();
                        }
                    }
                }
                finally
                {
                    // Close store.
                    store.Close();
                    chainList.Dispose();
                    criteria.Dispose();
                }

                return certificates;
            }
 internal static uint VerifyChainPolicy(SafeFreeCertChain chainContext, ref ChainPolicyParameter cpp)
 {
     ChainPolicyStatus ps = new ChainPolicyStatus {
         cbSize = ChainPolicyStatus.StructSize
     };
     UnsafeNclNativeMethods.NativePKI.CertVerifyCertificateChainPolicy((IntPtr) 4L, chainContext, ref cpp, ref ps);
     return ps.dwError;
 }
 internal unsafe bool VerifyRemoteCertificate(RemoteCertValidationCallback remoteCertValidationCallback)
 {
     SslPolicyErrors none = SslPolicyErrors.None;
     bool flag = false;
     X509Chain chain = null;
     X509Certificate2 remoteCertificate = null;
     try
     {
         X509Certificate2Collection certificates;
         remoteCertificate = this.GetRemoteCertificate(out certificates);
         this.m_IsRemoteCertificateAvailable = remoteCertificate != null;
         if (remoteCertificate == null)
         {
             none |= SslPolicyErrors.RemoteCertificateNotAvailable;
         }
         else
         {
             chain = new X509Chain {
                 ChainPolicy = { RevocationMode = this.m_CheckCertRevocation ? X509RevocationMode.Online : X509RevocationMode.NoCheck, RevocationFlag = X509RevocationFlag.ExcludeRoot }
             };
             if (certificates != null)
             {
                 chain.ChainPolicy.ExtraStore.AddRange(certificates);
             }
             if (!chain.Build(remoteCertificate) && (chain.ChainContext == IntPtr.Zero))
             {
                 throw new CryptographicException(Marshal.GetLastWin32Error());
             }
             if (this.m_CheckCertName)
             {
                 ChainPolicyParameter cpp = new ChainPolicyParameter {
                     cbSize = ChainPolicyParameter.StructSize,
                     dwFlags = 0
                 };
                 SSL_EXTRA_CERT_CHAIN_POLICY_PARA ssl_extra_cert_chain_policy_para = new SSL_EXTRA_CERT_CHAIN_POLICY_PARA(this.IsServer);
                 cpp.pvExtraPolicyPara = &ssl_extra_cert_chain_policy_para;
                 fixed (char* str = ((char*) this.m_HostName))
                 {
                     char* chPtr = str;
                     ssl_extra_cert_chain_policy_para.pwszServerName = chPtr;
                     cpp.dwFlags |= 0xfbf;
                     SafeFreeCertChain chainContext = new SafeFreeCertChain(chain.ChainContext);
                     if (PolicyWrapper.VerifyChainPolicy(chainContext, ref cpp) == 0x800b010f)
                     {
                         none |= SslPolicyErrors.RemoteCertificateNameMismatch;
                     }
                 }
             }
             X509ChainStatus[] chainStatus = chain.ChainStatus;
             if ((chainStatus != null) && (chainStatus.Length != 0))
             {
                 none |= SslPolicyErrors.RemoteCertificateChainErrors;
             }
         }
         if (remoteCertValidationCallback != null)
         {
             flag = remoteCertValidationCallback(this.m_HostName, remoteCertificate, chain, none);
         }
         else if ((none == SslPolicyErrors.RemoteCertificateNotAvailable) && !this.m_RemoteCertRequired)
         {
             flag = true;
         }
         else
         {
             flag = none == SslPolicyErrors.None;
         }
         if (!Logging.On)
         {
             return flag;
         }
         if (none != SslPolicyErrors.None)
         {
             Logging.PrintInfo(Logging.Web, this, SR.GetString("net_log_remote_cert_has_errors"));
             if ((none & SslPolicyErrors.RemoteCertificateNotAvailable) != SslPolicyErrors.None)
             {
                 Logging.PrintInfo(Logging.Web, this, "\t" + SR.GetString("net_log_remote_cert_not_available"));
             }
             if ((none & SslPolicyErrors.RemoteCertificateNameMismatch) != SslPolicyErrors.None)
             {
                 Logging.PrintInfo(Logging.Web, this, "\t" + SR.GetString("net_log_remote_cert_name_mismatch"));
             }
             if ((none & SslPolicyErrors.RemoteCertificateChainErrors) != SslPolicyErrors.None)
             {
                 foreach (X509ChainStatus status in chain.ChainStatus)
                 {
                     Logging.PrintInfo(Logging.Web, this, "\t" + status.StatusInformation);
                 }
             }
         }
         if (flag)
         {
             if (remoteCertValidationCallback != null)
             {
                 Logging.PrintInfo(Logging.Web, this, SR.GetString("net_log_remote_cert_user_declared_valid"));
                 return flag;
             }
             Logging.PrintInfo(Logging.Web, this, SR.GetString("net_log_remote_cert_has_no_errors"));
             return flag;
         }
         if (remoteCertValidationCallback != null)
         {
             Logging.PrintInfo(Logging.Web, this, SR.GetString("net_log_remote_cert_user_declared_invalid"));
         }
     }
     finally
     {
         if (chain != null)
         {
             chain.Reset();
         }
         if (remoteCertificate != null)
         {
             remoteCertificate.Reset();
         }
     }
     return flag;
 }