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))); }
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)); }
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)); }
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 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; }